DRF 3.x Throttling 节流使用示例和配置方法

Throttling (节流) 适用于和 Permissions 相似的功能,但节流的状态返回是临时性的, 适用于客户端向服务端发送请求的速率限制。

和权限一样可以单独指定相关的视图进行单独的节流设置,但你也可以指定多个节流方案,例如用户访问每分钟最多访问 60 次,每天最多访问 2000 次。

限制用于确定是否应授权请求。控制客户端可以向 API 发出的请求的速率。

标识客户端 HTTP 标头和 REMOTE_ADDR WSGI 变量用于标识客户端 IP 地址以进行限制。

Throttling 节流

框架中的限制始终定义为列表对象,在运行视图主体之前,优先检查列表中的每个节流对象,如果检查失败,将引发 exceptions.Throttled 异常并且视图主体将不运行。

Throttling 全局配置

使用 DEFAULT_THROTTLE_CLASSES 和 DEFAULT_THROTTLE_RATES 进行全局性设置默认的限制策略,所用的速率的描述 DEFAULT_THROTTLE_RATES 可以包括 second、minute、hour 或 day 作为节流段描述字符串。

身份验证用户每天可以调用 API 端点 50 次,匿名用户每天可以调用 10 次。

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

Throttling 局部配置

可以使用基于类的视图基于每个 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(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
    content = {
        'status': 'request was permitted'
    }
    return Response(content)


Throttling 应用示例

识别客户端方式

HTTP header 中 X-Forwarded-For 和 WSGI 变量 REMOTE_ADDR 被用来唯一标识节流客户端的 IP 地址。

如果存在 X-Forwarded-For 标头则将使用,否则将使用 WSGI 环境中的 REMOTE_ADDR 变量值,需要严格标识唯一的客户端 IP 地址需要先通过设置 NUM_PROXIES 配置 API 的应用代理数量。

此设置应为零或更大的整数,如果设置为 非零则 X-Forwarded-For 一旦首次排除任何应用程序代理 IP 地址,客户端 IP 将被标识为标头中的最后一个 IP 地址。

如果设置为 零则该 REMOTE_ADDR 值将始终用作标识IP地址,配置此 NUM_PROXIES 设置经过 NAT 转换的网关后面的所有客户端都将被视为单个客户端。

设置缓存

框架提供的节流类使用 Django 的缓存后端,对于简单的 LocMemCache 设置可以使用后端的默认值。

如果需要使用 default 以外的其他缓存,可以通过创建自定义的节流类并设置 cache 属性来实现。

在 DEFAULT_THROTTLE_CLASSES 设置键或使用 throttle_classesview 属性中设置自定义节流类。

from django.core.cache import caches

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

AnonRateThrottle

用于限制非验证用户,传入请求的 IP 地址用于生成唯一的密钥以进行限制。

允许的请求速率由以下之一确定(按优先顺序)。类的 rate 属性, 可以通过重写 AnonRateThrottle 并设置该属性来提供,该 DEFAULT_THROTTLE_RATES['anon'] 设置限制来自未知来源的请求速率,则使用 AnonRateThrottle。

REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': [
            'example.throttles.BurstRateThrottle',
            'example.throttles.SustainedRateThrottle'
        ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '10/day',
        ......
    }
}

UserRateThrottle

用于验证用户,在 UserRateThrottle 将节流用户跨 API 请求给定的速度,用户 ID 用于生成唯一的密钥以进行限制。未经身份验证的请求将退回到使用传入请求的 IP 地址来生成唯一密钥以进行限制,允许的请求速率由按优先顺序确定。

设置多用户,设置多个用户节流。

class BurstRateThrottle(UserRateThrottle):
    scope = 'burst'

class SustainedRateThrottle(UserRateThrottle):
    scope = 'sustained'

settings.py 中进行全局设置。一个 API 可能同时具有多个 UserRateThrottles 位置,为此请重写 UserRateThrottle 并为每个类设置一个唯一的作用域。

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'example.throttles.BurstRateThrottle',
        'example.throttles.SustainedRateThrottle'
    ],
    'DEFAULT_THROTTLE_RATES': {
        'burst': '60/min',
        'sustained': '1000/day'
    }
}

ScopedRateThrottle

用于指定视图,ScopedRateThrottle 类可用于限制访问 API 的特定部分,当所访问的视图包含 .throttle_scope 属性时才会应用此限制,然后通过将请求的 范围 与唯一的用户 ID 或 IP 地址串联起来即可形成唯一的限制键,允许的请求速率由 DEFAULT_THROTTLE_RATES 设置使用请求范围中的键确定。

views.py 中视图节流设置。

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

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

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

settings.py中进行全局设置,用户每天对一个请求的请求 ContactListView 或 ContactDetailView 将被限制为总共 1000 个请求, 用户对的请求 UploadView 将被限制为每天 20 个请求。

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'rest_framework.throttling.ScopedRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        'contacts': '1000/day',
        'uploads': '20/day'
    }
}

自定义节流

要创建自定义节流阀类,需要覆盖 BaseThrottle 并实现 .allow_request(self, request, view) 方法,允许该请求则该方法应返回 True,否则返回 False。

可以重写 .wait() 方法,.wait() 应返回建议的等待秒数然后再尝试下一个请求或者不返回,只有在 .allow_request() 之前返回 False 时才会调用 .wait() 方法,如果实现了.wait()方法并限制了请求,则响应中将包含 Retry-After 信息。

如果该 .wait() 方法已实现且请求已被限制则 Retry-After 标头将包含在响应中。

速率调节将在每10个请求中随机调节1个。

import random

class RandomRateThrottle(throttling.BaseThrottle):
    def allow_request(self, request, view):
        return random.randint(1, 10) != 1


示例   方法   DRF
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章