一 什么是throttle
简介:Django restframework的throttle可以对接口访问的频次进行限制,以减轻服务器压力。就是通常一个用户在多次请求一个页面,或者点击一个链接的时候,前几次点击是没有问题的,但是一旦连续几次之后,就会出现访问受限,离下一次访问还有50秒等的字样,在django rest framework 中有一个专门的组件来做限制访问。
思路:一旦一个用户向资源发送请求,那么根据用户的身份就有两种情况,匿名用户和认证用户。那么根据用户的身份怎么做限制访问?就是要找到用户的唯一标识。
- 匿名用户:对于匿名用户,唯一能用来标识的只有请求的IP。
- 认证用户:认证用户的用户名,或者用户ID等。
用户标识的问题解决了,假设设置的是每分钟只能访问5次,也就是5次/min。当用户发送请求,可以拿到用户的唯一标识,判断用户是第几次访问。有下面几种情况:
- 第一到五次:这是可以通过的,返回资源。
- 第六次(一分钟之内):请求被禁止,并返回提示信息。
- 第六次(一分钟之后):请求别允许,返回资源。
二 Django restframework的throttle实现
- 在Django rest framework中主要是通过throttling.py文件里面的几个类来实现限流功能的。
实现类
- 在整个流程上是在dispatch中的调用的initial方法中的self.check_throttles(request)调用到throttle类中的方法
调用入口
- throttle策略的配置:
① 全局配置settings.py
REST_FRAMEWORK = {
# 自定义限流类
'DEFAULT_THROTTLE_CLASSES': ['api.utils.throttle.VisitThrottle', ],
# 定义限流速率(支持天数/时/分/秒的限制)
'DEFAULT_THROTTLE_RATES': {
'throttle_count': '3/m',
'user_throttle': '10/m',
},
}
② 将限流策略设置在视图CBV
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)
③ 将限流策略设置在视图FBV
@api_view(['GET'])
@throttle_classes([UserRateThrottle])
def example_view(request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)
三 Django rest framework中throttle的执行流程
- 调用check_throttles方法,在这个方法中会遍历通过self.get_throttles()获取到的限流对象列表,默认列表里面是空的。也就是说默认不会有限流的策略。
获取限流对象列表
限流对象列表
- 在视图函数里面配置参数,让其应用上限流策略。我们这里以UserRateThrottle这个限流方法为例。(配置如第二节中的settings.py配置和FBV配置),在这里继续第二步的操作,执行UserRateThrottle对象的allow_request方法。
由于UserRateThrottle这个类本身没有allow_request方法,所以在其父类SimpleRateThrottle中找这个方法.
- 执行allow_request方法,会首先判断是否定义了self.rate。根据self.rate执行,最终回去查找self.scope属性,而且这个属性是必须的。
- 在UserRateThrottle中查找到定义的scope="user", 接着执行self.key语句。这条语句最终调用了UserRateThrottle里面的get_cache_key方法。
此例中我们没有配置authenticate,所有会执行get_cache_key里面的get_indet方法,并最终返回了scope和ident被self.key接收(返回格式:throttle_user_127.0.0.1)。
- 返回self.key之后继续执行self.history,self.history会返回客户端的访问记录列表,并根据rate的配置去判断是否是要pop某一条访问记录。并最终根据列表长度和允许的长度做对比,判断客户端当前是否具有访问权限。
- 若最终check_throttles返回True,则继续执行dispatch。dispatch之后的操作请参考之前写的django rest framework流程。如果返回False,则会继续执行self.throttled(request, throttle.wait())。
- 执行父类SimpleRateThrottle里面的wait方法。这个方法主要用来向客户端返回还需要多少时间可以继续访问的提示。
上一章:Django:rest framework之认证(authentication)
下一章:Django:rest framework之序列化(Serializer)