django restframework框架四 截流
@(python之路)[django restframework框架四 截流]
django restframework框架四 截流
截流簡介
?用戶的訪問頻率控制。我們把一個人訪問的事件按戳添加列表中,或者是根據(jù)ip計數(shù)。例如:一分鐘訪問三次,過一分鐘pop一次。
截流組件
這里我們把截流組件拿出來。以后用得時候可以直接導(dǎo)入取用。
我們寫的也是參考源碼。
from rest_framework.throttling import SimpleRateThrottle
class UserRateThrottle(SimpleRateThrottle):
scope = 'user'
def get_cache_key(self, request, view):
if request.user:
# 如果已經(jīng)登錄,pk
ident = request.user
else:
# 如果沒有登錄,IP
ident = self.get_ident(request)
# 'throttle_%(scope)s_%(ident)s'
# throttle_user_fengfeng
return self.cache_format % {
'scope': self.scope,
'ident': ident
}
def allow_request(self, request, view):
if request.auth.user.user_type == 1:
# self.num_requests = 3
# self.duration = 60
pass
else:
self.num_requests = 6
return super(UserRateThrottle,self).allow_request(request, view)
配置文件添加
添加如下這行:
# 此緩存將內(nèi)容保存至文件
# 配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 注:其他配置同開發(fā)調(diào)試版本
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES':{
'user':'3/m'
},
}
在調(diào)用緩存得時候,是調(diào)用得源碼中
def allow_request(self, request, view):
if self.rate is None:
return True
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
# 這里我們得history開始時空列表,隨著用戶得訪問,我們將用戶得時間戳添加近列表;
# 等過一定時間,pop調(diào)一個。
self.history = self.cache.get(self.key, [])
self.now = self.timer()
while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success()
注意:這不是絕對得限制,我們可以針對注冊用戶做限制,匿名用戶只能做,ip限制。限制也不是絕對得。
緩存配置文件
源碼分析
我們 還是從dispatch進入主流程,看他的initial.
1
def initial(self, request, *args, **kwargs):
self.format_kwarg = self.get_format_suffix(**kwargs)
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
self.perform_authentication(request)
self.check_permissions(request)
# 截流頻率
self.check_throttles(request)
?這里就是截流具體要做的東西self.check_throttles(request),具體是怎么做的,我們接著看。
2
def check_throttles(self, request):
for throttle in self.get_throttles():
# 是否允許訪問(allow_request)。如果不允許訪問,就會拋出異常。
if not throttle.allow_request(request, self):
# 我們注意的是throttle.wait() 他是提示多久以后才可以訪問
self.throttled(request, throttle.wait())
這里的self.get_throttles()還是個列表生成式,在里面self.throttle_classes這里邊有它的默認配置。
throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
在我們使用的時候需要導(dǎo)入
from rest_framework.throttling import BaseThrottle
源碼分析:
3
class BaseThrottle(object):
def allow_request(self, request, view):
pass
def get_ident(self, request):
xff = request.META.get('HTTP_X_FORWARDED_FOR')
remote_addr = request.META.get('REMOTE_ADDR')
……
def wait(self):
pass
HTTP_X_FORWARDED_FOR這里拿的是請求相關(guān)信息。
REMOTE_ADDR拿的是ip。
4
# 匿名
class AnonRateThrottle(SimpleRateThrottle)
# 用戶
class UserRateThrottle(SimpleRateThrottle)
# 范圍
class ScopedRateThrottle(SimpleRateThrottle)
例子:
from rest_framework.throttling import SimpleRateThrottle
class UserView(APIView):
authentication_classes = [MyAuthtication,]
throttle_classes = [BaseThrottle,]
def get(self,request,*args,**kwargs):
self.dispatch
return HttpResponse("get")
def post(self,request,*args,**kwargs):
return HttpResponse("post")
def put(self,request,*args,**kwargs):
return HttpResponse("put")
def delete(self,request,*args,**kwargs):
return HttpResponse("delete")
?當我們這么做的時候(throttle_classes = [BaseThrottle,]),他會先做一步實例化。具體請看2他是這樣做的實例化。他會執(zhí)行__init__.py具體看一下:
class SimpleRateThrottle(BaseThrottle):
cache = default_cache
timer = time.time
cache_format = 'throttle_%(scope)s_%(ident)s'
scope = None
# DEFAULT_THROTTLE_RATES 定義訪問頻率的。
THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES
def __init__(self):
if not getattr(self, 'rate', None):
# 這里我們要具體分析get_rate具體做了什么。
self.rate = self.get_rate()
self.num_requests, self.duration = self.parse_rate(self.rate)
def get_rate(self):
if not getattr(self, 'scope', None):
msg = ("You must set either `.scope` or `.rate` for '%s' throttle" %
self.__class__.__name__)
raise ImproperlyConfigured(msg)
try:
# 找到我們的scope,scope=None
return self.THROTTLE_RATES[self.scope]
except KeyError:
msg = "No default throttle rate set for '%s' scope" % self.scope
raise ImproperlyConfigured(msg)
根據(jù)他在配置文件中添加得user:1/3我們可以分析它的源碼
class SimpleRateThrottle(BaseThrottle):
def parse_rate(self, rate):
"""
Given the request rate string, return a two tuple of:
<allowed number of requests>, <period of time in seconds>
"""
if rate is None:
return (None, None)
num, period = rate.split('/')
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration)
他是在這里做的處理;具體流程我們還需要在SimpleRateThrottle類中具體看一下,這里不叫簡單不在做詳細得解釋。
若有不懂得同學(xué),可以留言。

浙公網(wǎng)安備 33010602011771號