Rate Limiting with Kong API Gateway

Rate limiting with Kong API gateway

In this article, we will learn how to use Kong to manage API endpoints. The article is organized as follows:

"Hello World!" API

Tutorial on building a simple "Hello World" API using Python, FastAPI and Uvicorn

Create a FastAPI application

FastAPI

To create a simple FastAPI application in Python, begin by installing the FastAPI Python package:

pip install fastapi

You can consider using a virtual environment to isolate dependencies. Now, create a file named "main.py" for our API and add the following code:

from fastapi import FastAPI

app = FastAPI()

@app.get("/hello_world")
async def hello_world():
    return {"message": "Hello World!"}

This defines an API endpoint /hello_world that returns a "Hello World!" message.

API server with Uvicorn

Uvicorn

To set up a local server for your API, install Uvicorn package for Python:

pip install uvicorn

To start the server using Uvicorn, run

uvicorn main:app --host 127.0.0.1 --port 5000

This will make the API available at http://localhost:5000/hello_world. To test the API, use the command:

curl http://localhost:5000/hello_world'

If the API has been set up correctly, you will receive the following JSON response:

{"message": "Hello World!}}

Kong API gateway and rate limiting

Kong API gateway

In this section, we will configure Kong API gateway for rate limiting user's request to the FastAPI server.

Installing Kong as a Docker container

To install Kong on your system, you can use the docker compose file provided below.

services:
  postgres_kong:
    image: postgres:18.2
    container_name: postgres_kong
    restart: unless-stopped
    environment:
      POSTGRES_USER: demo_user
      POSTGRES_PASSWORD: strong_password
      POSTGRES_DB: kong
    volumes:
      - ./data/postgres:/var/lib/postgresql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U demo_user -d kong"] # Specify database name or else it will reuse username as database name
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - kong_api_gateway

  kong:
    image: kong:3
    container_name: kong
    restart: unless-stopped
    depends_on:
      postgres_kong:
        condition: service_healthy
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: postgres_kong
      KONG_PG_USER: demo_user
      KONG_ADMIN_LISTEN: 0.0.0.0:8001 # Without this Kong does not listen outside container
      KONG_PG_PASSWORD: strong_password
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_PROXY_ERROR_LOG: /dev/stderr
      KONG_ADMIN_ERROR_LOG: /dev/stderr
    ports:
      - "8000:8000"   # Public proxy
      - "8001:8001"   # Admin API (secure this in production)
    command: >
      sh -c "kong migrations bootstrap && kong start"
    networks:
      - kong_api_gateway

networks:
  kong_api_gateway:
    driver: bridge
    name: kong_api_gateway

To use this compose file, open a terminal in the working directory and execute the command:

docker compose up -d

Docker will automatically fetch all images from docker hub and start Kong as a docker container.

Interacting with Kong API gateway

By default, Kong listens on two ports: 8000 and 8001. Port 8000 is for clients to access API end points whereas port 8001 connects to Kong Admin API for managing the gateway. It is, therefore, important that you do not expose port 8001 publicly in the production environment.

Unrestricted access on FastAPI server

The hello world API, discussed in , is accessible on port 5000. Before proceeding with the configuration of Kong as the API gateway, it is recommended to implement this API as a Docker container. To try out this tutorial, you can download the docker compose file along with the hello_world python code.

To understand why we need Kong, send consecutive requests on hello_world API to observe that there is no inherent rate limit. As unrestricted access can possibly overload the server, we will learn how to use Kong as a API gateway to limit the rate of requests. We will do this in three parts. First, we will set up a service to store information about the hello world api. Next, we will declare a route to relay API request to this service. Finally, we will use a Kong plugin for rate limiting. Once the gateway is configured, you should also restrict public access to port 5000 so that only Kong gateway can be used to access the hello world API.

Kong Admin API

Kong Admin API on port 8001 allows us to manage the Kong API gateway.

Set up a service in Kong

Let's start by sending a GET request to the Kong Admin API on port 8001 to list all available services.

curl http://localhost:8001/services

At this point, no services are registered with Kong, so, the response will be an empty object. To set up the first service, send a POST request to the Kong Admin API to add a new service. The POST request shouuld also specify the desired name and the url of the service.

curl -X POST http://localhost:8001/services \
    --data "name=hello_world" \
    --data "url=http://fastapi:5000/hello_world"

I have set up the hello world API as another docker container. This allows me to use the docker service name in the url instead of IP address. Using the docker service name eliminates the problem of dynamic IP addresses. Also, it eliminates the need to expose port 5000 outside the docker network.

Once the service is registered, you can verify by sending another GET request to Kong Admin API and list all services.

curl http://localhost:8001/services

On a side note, if you want the returned json string to be easier to read, you can append | jq to the curl request. The jq tools formats the JSON output with proper indentation.

Set up a route in Kong

Now, send a POST request to Kong Admin API to set up a new route for the hello world service and specify the name and a desired path for this route as a part of the requst.

curl -X POST http://localhost:8001/services/hello_world/routes \
  --data "name=hello_world_through_gateway"
  --data "paths[]=/hello_world_through_gateway"

In case you want to verify that the route has been registered, you can send a GET request to the Kong Admin API to list down all routes

curl https://locahost:8001/routes

Let's go ahead and test the route. As mentioned earlier, Kong listens on port 8000 for API requests. So, send a GET request using the command:

curl http://localhost:8000/hello_world_through_gateway

The API should return the hello world message.

Set up the rate limit plugin in Kong

The basic configuration for Kong gateway is done. Now, we will set up a plugin to limit the API access rate. To achieve this, make a POST request to the Kong admin API and add a plugin to the hello_world service. For this, you need to specify the name of the plugin and configure the rate limit as a part of the request

curl -X POST http://localhost:8001/services/hello_world/plugins \
  --data "name=rate-limiting" \
  --data "config.minute=5"

For demonstration, I have configured the rate limit to 5 requests per minute. To verify that the plugin was successfully implemented, you can generate the list of all plugins associated with the hello_world service using the command:

curl http://localhost:8001/services/hello_world/plugins

To test the plugin, send consecutive requests to Kong gateway. You will notice that after 5 successful requests, Kong responds with a message that the rate limit for the service has been exceeded. While testing the rate limiting plugin, sometimes you will be able to make more than 5 successful requests. This is because the plugin uses a fixed time window to count the number of requests. So, if your multiple requests get split over two consecutive time windows, you will be able to make up to 10 successful API requests.

Author

Anurag Gupta is an M.S. graduate in Electrical and Computer Engineering from Cornell University. He also holds an M.Tech degree in Systems and Control Engineering and a B.Tech degree in Electrical Engineering from the Indian Institute of Technology, Bombay.


Comment

* Required information
1000
Drag & drop images (max 3)
Captcha Image
Powered by Commentics

Past Comments

No comments yet. Be the first!

Similar content