django限流
pip install django-redis
1. seetings配置
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
# 'CONNECTION_POOL_KWARGS': {'max_connections': 100}, # 最大连接数,可选
'PASSWORD': '123456'
}
}
}
2. 编写限流类
from django.core.cache import cache as default_cache
from rest_framework import exceptions
class ThrottleException(exceptions.APIException):
# status_code = status.HTTP_429_TOO_MANY_REQUESTS
# default_code = 'throttle'
# 上述不写也可以
pass
class MyRateThrottle(SimpleRateThrottle):
# cache = default_cache # 访问记录存放在django的缓存中,默认为这个,可不写
scope = 'user' # 用来构造缓存中的key,可任意字符串
THROTTLE_RATES = {'user': '10/m'} # user:缓存的key,也就是scope;s秒,m分,h小时,d天,10/m十次每分钟
def get_cache_key(self, request, view): # 返回用户标识
# 判断登录和未登录情况逻辑
if request.user:
ident = request.user.pk # 用户ID
else:
ident = self.get_ident(request) # 获取请求用户IP(去request找请求头)
return f'throttle_{self.scope}_{ident}'
def throttle_failure(self): # 限流时返回的信息,原带简易版
wait = self.wait() # 需要等待的时间
detail = {
'code': 1005,
'data': '访问频率限制',
'detail': f'需等待{int(wait)}s才能访问',
}
# 如果ThrottleException内容是pass,可以改写成exceptions.APIException(detail)
raise ThrottleException(detail)
3. 使用
# 视图类中使用
throttle_classes = [MyRateThrottle, ...]
4. 多个限流类
throttle_failure(self) 返回True
继续,False
超频但还会继续后续的限流类,所有限流类执行完毕后,求和所有返回False的等待时间
raise xxx:超出频率,抛出异常,将停止后续的执行。
可在视图类中设置多个限流类后的限流函数:
class View(xxx):
...
def throttle(self, request, wait):
detail = {
'code': 1005,
'data': '访问频率限制',
'detail': f'需等待{int(wait)}s才能访问',
}
raise ThrottleException(detail)
5. 全局配置
rest_framework = {
'DEFAULT_THROTTLE_CLASSES': ['限流类1路径', '限流类2路径', '限流类3路径', ...],
'DEFAULT_THROTTLE_RATES': {
'user': '10/m', # 可省略限流类THROTTLE_RATES的指定,可为某一类事件做固定频率的限制
'xxx': '20/m',
...
}
}