Как использовать ограничение скорости для работы с крупномасштабным доступом при разработке API

Node.js задняя часть сервер GitHub API ThinkJS
Как использовать ограничение скорости для работы с крупномасштабным доступом при разработке API

Примечание редактора: Как говорится, хорошо«Недостаточно параллелизма, машины компенсируют»Когда мы столкнулись с высокими одновременными запросами, увеличивает машину, является самой простыми и большими местными тирантами. Но в дополнение к оптимизации кода, как мы должны сделать это с ограниченными ресурсами? Сегодня мы пригласили MA @ студентов поделиться с нами своим опытом в этой области, надеясь помочь вам.

———

Чтобы разработать надежный веб-API, недостаточно думать о безопасности, есть еще один момент, который нам необходимо рассмотреть, а именно меры противодействия крупномасштабному доступу. Не только службы веб-API, но и любая служба, представленная в Интернете, будет время от времени сталкиваться с крупномасштабным внешним доступом, например, с горячими точками в реальном времени, такими как «Лухан Гуань Сяотун объявляет о романе». Когда сервер сталкивается с крупномасштабным доступом, он исчерпает ресурсы для обработки этих доступов и, следовательно, не сможет предоставить услугу. В это время не только эти масштабные визиты, но и никто не может установить соединение с серверной частью.

Мы можем легко получить доступ к веб-API через программу, поэтому сервер API, скорее всего, столкнется с высокой нагрузкой доступа.Для этой проблемы, как и для обычных веб-приложений, мы можем расширить службу API, что является правильным способом.Однако эта статья не обсуждает план расширения. Далее мы обсудим некоторые важные моменты ограничения скорости при работе с крупномасштабным доступом и как это сделать в проектах, разработанных ThinkJS.

Ограничить доступ пользователей

Чтобы решить проблему внезапного крупномасштабного доступа, наиболее реальным методом является ограничение количества посещений на одного пользователя. То есть определить максимальное количество посещений одного пользователя в единицу времени.Если пользователь превысил максимальное количество посещений, сервер будет напрямую отклонять и возвращать сообщение об ошибке при повторном доступе пользователя. Например, если пользователю разрешено только 20 раз в течение 10 минут вызывать API для получения SMS-кода подтверждения, когда пользователь инициирует 21-й запрос в течение 10 минут, сервер вернет сообщение об ошибке, и доступ будет возобновлен. после 10 минут. Если вы ограничиваете доступ, вы должны сначала решить следующие три проблемы:

  • Как определить значение ограничения скорости
  • Как определить единицу времени ограничения скорости
  • Когда сбрасывать значение ограничения скорости

Определить значение ограничения скорости

Для API-интерфейсов запросов с часто обновляемыми данными пользователям необходимо часто получать доступ к последним данным. Если он настроен на доступ только 10 раз в час, пользователи определенно будут недовольны и обратятся к альтернативным сервисам. Первоначальная цель ограничения скорости доступа состоит в том, чтобы иметь дело с сервером, перегруженным крупномасштабным доступом за короткий период времени и, следовательно, неспособным предоставлять услуги, но если это неудобно для пользователей, это не будет стоить потери, поэтому необходимо как можно лучше понять условия, при которых используется предоставленный API, а затем определить значение ограничения скорости.

Определить единицу времени ограничения скорости

В зависимости от онлайн-сервиса, некоторые будут использовать один день в качестве единицы времени количества посещений, но это немного длится для многих API. Предположим, что пользователь пишет скрипт для доступа к API и не знает модуль времени Количество посещений сначала, то, возможно, ему нужно ждать 24 часа, чтобы продолжить доступ к API или изменить свой аккаунт. Если мы займеемся 10 минут, чем момент времени для количества посещений, если количество посещений превышено, нам нужно только дождаться 10 минут, чтобы продолжить посещение. Хотя настройка времени устройства тесно связана с данными, возвращаемыми API, большинство публичных API установили время единицы около 1 часа.

Определяет, когда сбрасывать значение ограничения скорости

Когда пользователь превышает верхний предел доступа, как сервер возвращает ответное сообщение? В этом случае может быть возвращен код состояния «429 Too Many Request», подготовленный в протоколе HTTP. Код состояния 429 определен в RFC 6585, опубликованном в апреле 2012 года. Когда конкретный пользователь инициирует слишком много запросов в течение определенного периода времени, сервер может вернуть этот код состояния, чтобы указать на ошибку. Этот код состояния описан в документе RFC следующим образом:

429 Too Many Requests

   The 429 status code indicates that the user has sent too many
   requests in a given amount of time ("rate limiting").

   The response representations SHOULD include details explaining the
   condition, and MAY include a Retry-After header indicating how long

Как видно из приведенного выше описания, ответное сообщение должно содержать подробности ошибки и может быть полученоRetry-AfterСообщите пользователю, как долго ждать доступа к API.Retry-AfterЗаголовок указывает, как долго клиент должен ждать, прежде чем снова получить доступ. Используется в RFC документахMAYПометьте первую часть, там сказано, что даже если этот заголовок не будет отправлен проблем не будет, а в теле ответа плюс заголовок будет еще дружелюбнее.

Кроме того,Retry-AfterНе заголовок ответа, посвященный коду состояния 429. Этот заголовок определен в RFC 7231 для HTTP 1.1, а также включен в тело ответа серий 503 и 3xx. иRetry-AfterВ первой части для указания времени используются секунды, а также можно использовать подробную информацию о дате.Вы можете посмотреть описание в документе RFC:

Retry-After

   Servers send the "Retry-After" header field to indicate how long the
   user agent ought to wait before making a follow-up request.  When
   sent with a 503 (Service Unavailable) response, Retry-After indicates
   how long the service is expected to be unavailable to the client.
   When sent with any 3xx (Redirection) response, Retry-After indicates
   the minimum time that the user agent is asked to wait before issuing
   the redirected request.

   The value of this field can be either an HTTP-date or a number of
   seconds to delay after the response is received.

     Retry-After = HTTP-date / delay-seconds

   A delay-seconds value is a non-negative decimal integer, representing
   time in seconds.

     delay-seconds  = 1*DIGIT

Передайте информацию об ограничении скорости через HTTP-ответ

В процессе реализации ограничения скорости доступа было бы очень удобно, если бы пользователю сообщалось ограничение доступа текущего пользователя, количество использованных доступов и время сброса ограничения скорости доступа. Если эта информация не возвращается, пользователь может несколько раз попытаться получить доступ к API интерфейса, чтобы определить, снято ли ограничение скорости, что, несомненно, увеличит нагрузку на сервер.

Информация об ограничении скорости может быть помещена в заголовок ответного сообщения, а другая часть - как часть данных тела ответного сообщения.В настоящее время метод помещения информации об ограничении скорости в заголовок ответного сообщения стал стандарт де-факто.

Имя инструкция тип
X-RateLimit-Limit Лимит доступа в единицу времени Integer
X-RateLimit-Remaining Оставшиеся посещения Integer
X-RateLimit-Reset Время сброса посещений UTC epoch seconds

посмотриПолитика ограничения скорости GitHub, GitHub использует три приведенных выше заголовка ответа безRetry-Afterкапитал. Существует 5000 посещений в час для аутентифицированных запросов и 60 посещений в час для неаутентифицированных запросов.

иСтратегия ограничения скорости TwitterВременное окно GitHub составляет 15 минут, что намного меньше, чем у GitHub, потому что данные Twitter обновляются относительно быстро, а временное окно можно установить меньше, чтобы удовлетворить потребности пользователей в получении последних данных. Twitter использует заголовки ответов, аналогичные трем вышеприведенным, для передачи информации об ограничении скорости.x-rate-limit-limit,x-rate-limit-remaining,x-rate-limit-reset. Для первых двух запросов GET, один за 15 минут 15 запросов, другие 15 минут 180 запросов и разрешить только аутентификацию доступа.

Сравнивая политики ограничения скорости GitHub и Twitter, мы можем узнать, что, если информация об ограничении скорости передается точно, заголовок ответа может быть полностью определен сам по себе.Ключевым моментом является то, что семантика ясна и не может конфликтовать с другими стандартные заголовки.

Реализация контроля ограничения скорости API в ThinkJS

Чтобы реализовать ограничение скорости доступа к API, необходимо подсчитать, сколько раз каждый пользователь и приложение обращались к API, обычно используяRedisХранение равных пар ключ-значение для записи. ThinkJS сочетает в себе собственный метод сопоставления маршрутов для достиженияthink-ratelimiterпара промежуточного программного обеспеченияactionДля ограничения скорости необходимоmiddleware.jsСледующая конфигурация может быть сделана для реализации простой политики ограничения скорости.

// in middleware.js
const redis = require('redis');
const { port, host, password } = think.config('redis');
const db = redis.createClient(port, host, { password });
const ratelimiter = require('think-ratelimiter');

module.exports = {
  // after router middleware
  {
    handle: ratelimiter,
    options: {
      db,
      errorMessage: 'Sometimes You Just Have To Slow Down',
      headers: {
        remaining: 'X-RateLimit-Remaining',
        reset: 'X-RateLimit-Reset',
        total: 'X-RateLimit-Limit'
      },
      resources: {
        'test/test': { // key 是 controller/action 的拼接
          id: ctx => ctx.ip,
          max: 5,
          duration: 7000 // ms
        }
      }
    }
  },
}

заголовок тела ответаX-RateLimit-ResetУказывает время, когда доступ может быть восстановлен, сRetry-AfterЗаголовок, значением которого является количество секунд до времени восстановления.

Суммировать

В веб-приложении, разработанном ThinkJS, вы можете использовать промежуточное программное обеспечение, а затем добавить конфигурацию для достижения простого ограничения скорости.Если предоставляемая вами служба веб-API имеет большой объем доступа или требует оплаты доступа и других функций, вам необходимо добавить уровень перед реальной логикой.Чтобы делать вещи, связанные с ограничением скорости, можно реализовать в ThinkJSservices/ratelimit.js, то в проектеbase controllerРеализовать логику, такую ​​как ограничение скорости в

Использованная литература: