7-1 频率-DRF限制频率
目录:
- 节流的介绍
- SimpleRateThrottle 源码分析
- 自定义限制频率(节流)
一、节流介绍
开放平台的API接口调用需要限制其频率,以节约服务器资源和避免恶意的频繁调用。其实有的时候我们辛辛苦苦造的数据被爬虫份子给爬掉。爬虫在爬数据的时候数据量也比较大,那么这个时候就会给我们服务器造成了压力,影响用户的使用。在这个时候我们就要限制用户的使用频率。那怎么限制呐?我们给出一些限制的思路:
节流思路:
我现在想 限制 每个用户 1分钟之内 只能访问 3次(3/min),并且每个用户在访问的时候,我按一定的规则记录当前用户访问的记录,比如我按 ip地址记录:
{"127.0.0.1": {"12:29:50","12:29:40","12:29:20'"}}:指的是 我 127.0.0.1 ip地址在1分钟之内访问 3次。这个时候我在 12:30:10 去访问时,在1分钟之内,很明显无法访问。
那我如果是 12:30:21 去访问,这个时候 12:30:21 跟 {"127.0.0.1": {"12:29:50","12:29:40","12:29:20'"}} 中最后一个值 12:29:20 比,大于1分钟了,这个时候可以访问了。
那个这个时候 列表就变成: {"127.0.0.1": {"12:30:21","12:29:50","12:29:40"}} 就把 12:30:21 加到列表中第一个参数,把 12:29:20列表中删除掉。
依次类推...
二、SimpleRateThrottle 源码分析
2.1、导入 SimpleRateThrottle
from rest_framework.throttling import SimpleRateThrottle
2.2、查看源码
Ctrl + SimpleRateThrottle -> BaseThrottle
发现它是继承一个基础类 Ctrl + BaseThrottle ,有哪些东西:
class BaseThrottle(object):
"""
Rate throttling of requests.
"""
def allow_request(self, request, view): #必须要实现的1个方法,True:允许访问 False:禁止访问
"""
Return `True` if the request should be allowed, `False` otherwise.
"""
raise NotImplementedError('.allow_request() must be overridden')
def get_ident(self, request):
.....
def wait(self):
.....
好啦,我们再来看看 SimpleRateThrottle 类:发现有一个 scope = None 属性,这个属性是要配置的。为什么呐?因为 它要去读取限制用户到底多长时间读取一次。
2.3、内置节流类
说明:我们来看看 我们内置的节流类有哪些,他们跟SimpleRateThrottle源码在一个文件中
class AnonRateThrottle(SimpleRateThrottle): """ 限制匿名用户 """ scope = 'anon' def get_cache_key(self, request, view): if request.user.is_authenticated: return None # Only throttle unauthenticated requests. return self.cache_format % { 'scope': self.scope, 'ident': self.get_ident(request) #获取IP地址 } class UserRateThrottle(SimpleRateThrottle): """ 限制已认证用户 """ scope = 'user' def get_cache_key(self, request, view): if request.user.is_authenticated: ident = request.user.pk #用户主键当标识 else: ident = self.get_ident(request) return self.cache_format % { 'scope': self.scope, 'ident': ident } class ScopedRateThrottle(SimpleRateThrottle): """ 每个用户对视图的访问次数 """ scope_attr = 'throttle_scope' def __init__(self): # Override the usual SimpleRateThrottle, because we can't determine # the rate until called by the view. pass def allow_request(self, request, view): # We can only determine the scope once we're called by the view. self.scope = getattr(view, self.scope_attr, None) # If a view does not have a `throttle_scope` always allow the request if not self.scope: return True # Determine the allowed request rate as we normally would during # the `__init__` call. self.rate = self.get_rate() self.num_requests, self.duration = self.parse_rate(self.rate) # We can now proceed as normal. return super(ScopedRateThrottle, self).allow_request(request, view) def get_cache_key(self, request, view): """ If `view.throttle_scope` is not set, don't apply this throttle. Otherwise generate the unique cache key by concatenating the user id with the '.throttle_scope` property of the view. """ if request.user.is_authenticated: ident = request.user.pk else: ident = self.get_ident(request) return self.cache_format % { 'scope': self.scope, 'ident': ident }
源码已经搞好啦。
三、自定义限制频率(节流)
3.1、新建内置频率类
说明:在应用下新建一个throttlings文件。创建频率类:
from rest_framework.throttling import SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
scope = "未认证用户"
def get_cache_key(self, request, view):
return self.get_ident(request) #ip地址当做key,可以会缓存到django的缓存里面
class UserThrottle(SimpleRateThrottle):
scope = "已认证用户"
def get_cache_key(self, request, view): #要写一个认证方法,告诉人家你拿什么当key
return request.user #当前登录用户当做key
好了,频率类 新建好了。
3.2、全局配置
说明:在settings.py的REST_FRAMEWORK 下配置全局。
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ....,
'DEFAULT_PERMISSION_CLASSES': ...,
'DEFAULT_THROTTLE_CLASSES': ['app05.throttlings.UserThrottle', ],
'DEFAULT_THROTTLE_RATES': {
'未认证用户': '3/m',
'已认证用户': '10/m',
},
}
意思是:未认证用户 1分钟3次,认证用户是 1分钟10次。那这个时间定义在哪里定义的呐?SimpleRateThrottle源码中有,我们来看看:
class SimpleRateThrottle(BaseThrottle):
"""
...
Period should be one of: ('s', 'sec', 'm', 'min', 'h', 'hour', 'd', 'day') #时间设置
....
"""
....
3.3、局部配置
说明:上面是全局配置,但是有的时候我不想全局的,我只想局部实现,那咋办呐?
....
from .throttlings import VisitThrottle #导入自定义频率类
# Create your views here.
class CartView(APIView):
# 节流 局部配置
throttle_classes = [VisitThrottle]
def get(self, request, *args, **kwargs):
....
return JsonResponse(ctx)
但是全局也写了,我只想在视图中什么限制也不想加,那我们可以是 throttle_classes 为空就行了,如下:
class CartView(APIView):
# 视图不加任何限制,但是全局已经配置了
throttle_classes = []
...
3.4、测试结果
1、已认证用户

2、未认证用户


浙公网安备 33010602011771号