【djangorestframework】11、Throttling(限流)
限流(Throttling)
- 限流类似于权限,因为它确定是否应该授权请求。限流阀表示临时状态,并用来控制客户端对API的请求速率。
- 与权限一样,可能会使用多种限流方式。你的API可能对未经身份验证的请求进行限流,对经过身份验证的请求限流较少。
- 如果你想同事施加突发节流速率和持续节流速率,还可以使用多个限流阀。例如,你可能希望将用户限制为每分钟最多60个请求,每天1000个请求。
- 限流阀不一定只指限速请求。例如,存储服务可能还需要限制宽带,而付费数据服务可能希望限制访问的记录的特定数量。
如何确定限流(How throttling is determined)
- 与权限和身份验证一样,REST framework中的限流始终定义为类列表。
- 在运行视图主体之前,检查列表中的每个限流阀。如果任何限流检查失败,将引发exceptions.Throttled异常,并且该视图的主体将不会再执行。
设置限流策略(Setting the throttling policy)
- 使用DEFAULT_THROTTLE_CLASSES和DEFAULT_THROTTLE_RATES settings可以设置全局的默认限流策略。例如:
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中使用的频率描述可能包括scond,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)
如何识别客户端(How clients are identified)
- X-Forwarded-For HTTP标头和REMOTE_ADDR WSGI变量用于为限流的唯一标识的客户端IP地址。如果存在X-Forwarded-For标头,则将使用它,否则将使用WSGI环境中的REMOTE_ADDR变量的值。
- 如果你需要严格标识唯一的客户端IP地址,则需要首先通过设置NUM_PROXIES设置来配置API运行的应用程序代理的数量。此设置应为零活或最大的整数。如果设置为非零,则一旦任何应用程序代理IP地址首先被排除,客户端IP将被标识为X-Forwarded-For标头中的最后一个IP地址。如果设置为零,则REMOTE_ADDR值将始终用作识别IP地址。
- 重要的是要理解,如果配置NUM_PROXIES设置,那么唯一的NAT网关后面的所有客户端将被视为单个客户端。
- 关于X-Forwarded-For标头如何工作以及识别远程客户端IP的更多上下文可以在这里找到。
设置缓存(Setting up the cache)
- REST framework提供的限流类使用Django的缓存后端。你应该确保你已经设置了适当的缓存设置。对于简单的设置,LocMemCache后端的默认值应该没问题。有关更多详细信息,请查阅Django的缓存文档。
- 如果你需要使用default以外的缓存,则可以通过创建自定义限流类并设置cache属性来实现。例如:
class CustomAnonRateThrottle(AnonRateThrottle):
cache = get_cache('alternate')
- 你还需要记住在'DEFAULT_THROTTLE_CLASSES' settings键中设置自定义的限流类,或者使用throttle_classes视图属性。
API参考
AnonRateThrottle
- AnonRateThrottle只会限制未经认证的用户。传入请求的IP地址用于生成唯一的键来限流。
- 允许的请求率由以下之一决定(按优先顺序)
- 类上的rate属性,可以通过重写AnonRateThrottle并设置其属性来提供
- DEFAULT_THROTTLE_RATES['anon']设置。
- 如果你想限制未知来源的请求率,AnonRateThrottle是合适的。
UserRateThrottle
- UserRateThrottle将通过API限制用户的给定请求率。用户id用于生成唯一的密钥来加以限制。未经身份验证的请求将回退到使用传入请求的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'
}
}
- 如果希望对每个用户进行简单的全局速率限制,那么是合适的。
ScopedRateThrottle
- ScopedRateThrottle类可用于限制对API特定部分的访问。只有当正在访问的视图包含.throttle_scope属性时才会应用此限制。然后通过将请求的"范围"与唯一的用户id或IP地址连接起来形成唯一的限流密钥。
- 允许的请求率由DEFAULT_THROTTLE_RATES setting使用请求"范围"中的键确定。
- 例如,给出以下视图...
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': {
'contacts': '1000/day',
'uploads': '20/day'
}
}
- 用户对ContactListView或ContactDetailView的请求将被限制为每天1000次。用户对UploadView的请求将被限制为每天20次。
自定义限流(Custom throttles)
- 要创建自定义限流,请重写BaseThrottle类并实现.allow_request(self, request, view)。如果请求被允许,该方法应返回True,否则返回False
- 还可以选择重写.wait()方法。如果实现,.wait()应返回在尝试下一次请求之前等待的推荐秒数,或者返回None。如果.allow_request()先前已经返回False,则只会调用.wait()方法。
- 如果.wait()方法被实现并且请求收到限制,那么Retry-After标头将包含在响应中。
- 举个例子
- 以下是速率限制的示例,它将随机地限制10次请求中的1次。
import random
class RandomRateThrottle(throttling.BaseThrottle):
def allow_request(self, request, view):
return random.randint(1, 10) != 1
本文来自博客园,作者:郭祺迦,转载请注明原文链接:https://www.cnblogs.com/guojie-guojie/p/16190704.html
分类:
Django
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!