Traffic limiting scenario: The capability of service provision is limited. To prevent the service from being overwhelmed by a large number of requests, you can limit the flow of service requests through the gateway. For example, a service can process only 100 requests for 1s. The requests exceeding the traffic limit threshold are discarded.

A, rate limiting

The Kong gateway supports rate-limiting

1.1 Configuration Parameters

You can get this information from the plug-in parameters:

  1. There are three granularity types supported for traffic limiting:consumer,credential,ip, the default is consumer
  2. Storage policies support the following three types:local,cluster,redis, the default is Cluster. The stored contents are as followsfmt("ratelimit:%s:%s:%s:%s", api_id, identifier, period_date, name)Is key, and the number of continuous accesses is value.
  • Local: Stores shared content in Nginx – supports interwork access
  • Cluster: in the databaserate-limitingTable in – Cluster access supported
  • Redis: Plug-in configuration in Redis – supports cluster access
  1. Supports traffic limiting in various time units
  fields = {
    second = { type = "number" },
    minute = { type = "number" },
    hour = { type = "number" },
    day = { type = "number" },
    month = { type = "number" },
    year = { type = "number" },
    limit_by = { type = "string", enum = {"consumer"."credential"."ip"}, default = "consumer" },
    policy = { type = "string", enum = {"local"."cluster", REDIS}, default = "cluster" },
    fault_tolerant = { type = "boolean", default = true },
    redis_host = { type = "string" },
    redis_port = { type = "number", default = 6379 },
    redis_password = { type = "string" },
    redis_timeout = { type = "number", default = 2000 },
    redis_database = { type = "number", default = 0 },
    hide_client_headers = { type = "boolean", default = false}},Copy the code

1.2 Current limiting granularity

When the restriction type (restriction granularity) is consumer and identifier, traffic limiting plug-ins need to inject authentication information into nginx.ctx, such as JWT, key-Auth, and oAuth2

  if conf.limit_by == "consumer" then
    identifier = ngx.ctx.authenticated_consumer and ngx.ctx.authenticated_consumer.id
    if not identifier and ngx.ctx.authenticated_credential then -- Fallback on credential
      identifier = ngx.ctx.authenticated_credential.id
    end
  elseif conf.limit_by == "credential" then
    identifier = ngx.ctx.authenticated_credential and ngx.ctx.authenticated_credential.id
  end# If there is no authentication in the request, granularity degrades to IP limitingif not identifier then
    identifier = ngx.var.remote_addr
  end
  
Copy the code

1.3 Traffic limiting Algorithm

A common approach to limiting traffic is the number of requests over a period of time. However, if you limit the time by a period of time, you will encounter the problem of uneven flow distribution. For example, if a service has a limit of 3600 requests per hour, then at some point a number of requests come in and exceed the threshold. To solve this problem, Kong took down a period of time, setting the threshold at 60 beats per minute per second.

  local limits = {
    second = conf.second,
    minute = conf.minute,
    hour = conf.hour,
    day = conf.day,
    month = conf.month,
    year = conf.year
  }
Copy the code

Calculate the remaining. Each time the request comes in, the plugin gets the number of remaining requests from the store and returns the usage format (where name is the Metric of the limits definition mentioned above) :

    -- Recording usage
    usage[name] = {
      limit = limit,
      remaining = remaining
    }
    -- Mark that Metric stopped
    if remaining <= 0 then
      stop = name
    end
Copy the code

Then minus one

  if usage then
    -- Adding headers
    if not conf.hide_client_headers then
      for k, v in pairs(usage) do
        ngx.header[RATELIMIT_LIMIT .. "-". k] = v.limit-- -increment_value for this current request
        ngx.header[RATELIMIT_REMAINING .. "-". k] =math.max(0, (stop == nil or stop == k) and v.remaining - 1 or v.remaining) 
      end
    end
Copy the code

Second, on limiting the flow

Reference:

  1. Some implementations of service traffic limiting algorithms are discussed
  2. Java Concurrency Utility class (Semaphore)
  3. Redis Deep Adventures: Core Principles and Applied Practices