Плагин Kong дросселирования

Архитектура

Сценарии ограничения тока. Возможности, предоставляемые службой, ограничены. Чтобы большое количество запросов не тормозило сервис, можно ограничить поток запросов к сервису через шлюз. Например, служба может обрабатывать только 100 запросов в секунду, а запросы, превышающие текущий предельный порог, отбрасываются.

1. ограничение скорости

Плагины ограничения тока, предоставляемые Kong gateway:rate-limiting

1.1 Настраиваемые параметры

Эту информацию можно получить из параметров плагина:

  1. Существует три степени детализации поддержки регулирования:consumer,credential,ip, по умолчанию используется потребительский
  2. Существует три поддерживаемых политики хранения:local,cluster,redis, по умолчанию используется кластер. Сохраняемый контент:fmt("ratelimit:%s:%s:%s:%s", api_id, identifier, period_date, name)является ключом, а количество непрерывных доступов является значением.
  • local: хранит общий контент в Nginx — поддерживает межпроцессный доступ с несколькими рабочими процессами.
  • кластер: в базе данныхrate-limitingТаблица — Поддержка доступа к кластеру
  • redis: плагин, настроенный в Redis — поддерживает доступ к кластеру
  1. Поддерживает ограничение тока для различных единиц времени
  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 },
  },

1.2 Детализация ограничения тока

Когда тип ограничения (детализация ограничения)consumerиidentifierКогда подключаемому модулю ограничения тока требуется некотороеnginx.ctxПлагины, которые вводят информацию для аутентификации, например: jwt, key-auth, 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
  # 如果请求中不带认证,粒度会退化到IP限流
  if not identifier then
    identifier = ngx.var.remote_addr
  end
  

1.3 Алгоритм ограничения тока

Обычной практикой дросселирования является количество запросов за период времени. Однако если для ограничения времени используется только определенный период времени, возникает проблема неравномерного распределения трафика. Например, если сервис ограничивает количество запросов в час до 3600, то если куча запросов превысит порог в определенный момент. Чтобы решить эту проблему, Конг разделил период времени и установил пороговое значение 60 раз в секунду.

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

Рассчитать оставшееся. Каждый раз, когда приходит запрос, плагин получает количество обращений к текущему сервису, оставшееся (оставшееся) от хранилища, и возвращаетusageформат (где имя указано вышеlimitsопределенная метрика):

    -- Recording usage
    usage[name] = {
      limit = limit,
      remaining = remaining
    }
    -- 标记那个Metric停止了
    if remaining <= 0 then
      stop = name
    end

затем вычесть один

  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

2. Расскажите о текущем лимите

Ссылаться на:

  1. Расскажите о нескольких реализациях алгоритма ограничения тока обслуживания
  2. Класс инструментов параллелизма Java (семафор Semaphore)
  3. Redis Deep Adventure: основные принципы и практика применения