Дросселирование

HTTP/1.1 420 Повышение спокойствия

Twitter API rate limiting response

Дросселирование похоже на :doc:`permissions <permissions>`** , поскольку оно определяет, должен ли запрос быть авторизован. Дроссели обозначают временное состояние и используются для контроля скорости запросов, которые клиенты могут делать к API.

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

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

Несколько дросселей также можно использовать, если вы хотите установить как пакетное, так и постоянное дросселирование. Например, вы можете ограничить пользователя максимум 60 запросами в минуту и 1000 запросами в день.

Дросселирование не обязательно относится только к ограничению скорости запросов. Например, служба хранения данных может также нуждаться в ограничении пропускной способности, а платная служба данных может захотеть ограничить доступ к определенному количеству записей.

Как определяется дросселирование

Как и в случае с разрешениями и аутентификацией, дросселирование в REST-фреймворке всегда определяется как список классов.

Перед запуском основного тела представления проверяется каждый дроссель в списке. Если проверка какого-либо дросселя не удалась, будет вызвано исключение exceptions.Throttled, и основное тело представления не будет запущено.

Настройка политики дросселирования

Политика дросселирования по умолчанию может быть установлена глобально, с помощью параметров DEFAULT_THROTTLE_CLASSES и DEFAULT_THROTTLE_RATES. Например.

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '1000/day'
    }
}

Описание скорости, используемое в DEFAULT_THROTTLE_RATES, может включать second , minute , hour или day в качестве периода дросселирования.

Вы также можете установить политику дросселирования на основе каждого просмотра или каждого набора просмотров, используя APIView представления на основе классов.

from rest_framework.response import Response
from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView

class ExampleView(APIView):
    throttle_classes = [UserRateThrottle]

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)

Если вы используете декоратор @api_view с представлениями, основанными на функциях, вы можете использовать следующий декоратор.

@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

Также можно установить классы дросселирования для маршрутов, созданных с помощью декоратора @action. Установленные таким образом классы дросселирования будут переопределять любые настройки классов на уровне набора представлений.

@action(detail=True, methods=["post"], throttle_classes=[UserRateThrottle])
def example_adhoc_method(request, pk=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)

Как происходит идентификация клиентов

Заголовок HTTP X-Forwarded-For и переменная WSGI REMOTE_ADDR используются для уникальной идентификации IP-адресов клиентов для дросселирования. Если заголовок X-Forwarded-For присутствует, то он будет использоваться, в противном случае будет использоваться значение переменной REMOTE_ADDR из среды WSGI.

Если вам необходимо строго идентифицировать уникальные IP-адреса клиентов, вам нужно сначала настроить количество прокси-серверов приложений, за которыми работает API, установив параметр NUM_PROXIES. Это значение должно быть целым числом, равным нулю или больше. Если значение не равно нулю, то IP-адрес клиента будет идентифицирован как последний IP-адрес в заголовке X-Forwarded-For, после того как IP-адреса прокси приложений будут исключены. Если установлено нулевое значение, то в качестве идентифицирующего IP-адреса всегда будет использоваться значение REMOTE_ADDR>.

Важно понимать, что если вы настроите параметр NUM_PROXIES, то все клиенты за уникальным шлюзом NAT’d будут рассматриваться как один клиент.

Дальнейший контекст о том, как работает заголовок X-Forwarded-For, и идентификация IP удаленного клиента может быть found here.

Настройка кэша

Классы дросселей, предоставляемые фреймворком REST, используют бэкенд кэша Django. Вам следует убедиться, что вы установили соответствующее значение cache settings. Значение по умолчанию LocMemCache backend должно быть подходящим для простых настроек. Для получения более подробной информации смотрите cache documentation бэкенда Django.

Если вам нужно использовать кэш, отличный от 'default' , вы можете сделать это, создав пользовательский класс дросселя и установив атрибут cache. Например:

from django.core.cache import caches

class CustomAnonRateThrottle(AnonRateThrottle):
    cache = caches['alternate']

Вам нужно будет не забыть также установить свой пользовательский класс дросселя в ключе настроек 'DEFAULT_THROTTLE_CLASSES' или с помощью атрибута представления throttle_classes.


Справочник по API

AnonRateThrottle

AnonRateThrottle будет дросселировать только неаутентифицированных пользователей. IP-адрес входящего запроса используется для генерации уникального ключа для дросселирования.

Допустимая скорость запроса определяется по одному из следующих параметров (в порядке предпочтения).

  • Свойство rate на классе, которое может быть предоставлено путем переопределения AnonRateThrottle и установки свойства.

  • Настройка DEFAULT_THROTTLE_RATES['anon'].

AnonRateThrottle подходит, если вы хотите ограничить скорость запросов от неизвестных источников.

UserRateThrottle

UserRateThrottle будет дросселировать пользователей до заданной скорости запросов через API. Идентификатор пользователя используется для генерации уникального ключа для дросселирования. Неаутентифицированные запросы будут возвращаться к использованию IP-адреса входящего запроса для генерации уникального ключа для дросселирования.

Допустимая скорость запроса определяется по одному из следующих параметров (в порядке предпочтения).

  • Свойство rate на классе, которое может быть предоставлено путем переопределения UserRateThrottle и установки свойства.

  • Настройка DEFAULT_THROTTLE_RATES['user'].

API может иметь несколько UserRateThrottles одновременно. Для этого переопределите UserRateThrottle и установите уникальную «область видимости» для каждого класса.

Например, несколько скоростей дросселирования пользователя могут быть реализованы с помощью следующих классов…

class BurstRateThrottle(UserRateThrottle):
    scope = 'burst'

class SustainedRateThrottle(UserRateThrottle):
    scope = 'sustained'

…и следующие настройки.

REST_FRAMEWORK = {
„DEFAULT_THROTTLE_CLASSES“: [

„example.throttles.BurstRateThrottle“, „example.throttles.SustainedRateThrottle“

], „DEFAULT_THROTTLE_RATES“: {

„burst“: „60/min“, „sustained“: „1000/day“

}

}

UserRateThrottle подходит, если вам нужны простые глобальные ограничения скорости для каждого пользователя.

ScopedRateThrottle

Класс ScopedRateThrottle может быть использован для ограничения доступа к определенным частям API. Этот дроссель будет применяться только в том случае, если представление, к которому осуществляется доступ, включает свойство .throttle_scope. Уникальный ключ дросселя будет сформирован путем соединения «scope» запроса с уникальным идентификатором пользователя или IP-адресом.

Допустимая скорость запроса определяется настройкой DEFAULT_THROTTLE_RATES с помощью ключа из «области действия» запроса.

Например, учитывая следующие представления…

class ContactListView(APIView):
    throttle_scope = 'contacts'
    ...

class ContactDetailView(APIView):
    throttle_scope = 'contacts'
    ...

class UploadView(APIView):
    throttle_scope = 'uploads'
    ...

…и следующие настройки.

REST_FRAMEWORK = {
„DEFAULT_THROTTLE_CLASSES“: [

„rest_framework.throttling.ScopedRateThrottle“,

], „DEFAULT_THROTTLE_RATES“: {

„контакты“: „1000/день“, „загрузки“: „20/день“

}

}

Запросы пользователей к ContactListView или ContactDetailView будут ограничены до 1000 запросов в день. Запросы пользователей к UploadView будут ограничены 20 запросами в день.


Индивидуальные дроссели

Чтобы создать пользовательский дроссель, переопределите BaseThrottle и реализуйте .allow_request(self, request, view). Метод должен возвращать True, если запрос должен быть разрешен, и False в противном случае.

По желанию вы также можете переопределить метод .wait(). Если он реализован, .wait() должен возвращать рекомендуемое количество секунд ожидания перед попыткой следующего запроса, или None. Метод .wait() будет вызван только в том случае, если .allow_request() ранее вернул False.

Если реализован метод .wait() и запрос дросселируется, то в ответ будет включен заголовок Retry-After.

Пример

Ниже приведен пример дросселирования скорости, которое будет случайным образом дросселировать 1 из каждых 10 запросов.

import random

class RandomRateThrottle(throttling.BaseThrottle):
    def allow_request(self, request, view):
        return random.randint(1, 10) != 1
Вернуться на верх