限流的逻辑主要在throttling.py的SimpleRateThrottle类中的allow_request方法里。该方法中主要利用列表构建一个访问记录的队列,通过队列的长度来控制访问次数,通过访问记录中的时间戳,来控制时间,这里只截取allow_request方法进行分析。
class SimpleRateThrottle(BaseThrottle):
#当前时间戳
timer = time.time
def __init__(self):
if not getattr(self, 'rate', None):
self.rate = self.get_rate()
#主要获取配置中的设置的一定访问时间下的访问次数。
self.num_requests, self.duration = self.parse_rate(self.rate)
def allow_request(self, request, view):
#判断是否限制访问频率
if self.rate is None:
return True
#获取限制访问的标识符,可以是IP或者用户pk
self.key = self.get_cache_key(request, view)
if self.key is None:
return True
#根据标识获取访问记录列表
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()
#判断访问记录列表的长度是否大于等于配置中规定的访问次数,如果是则证明在
#该段时间内已经达到所限制的访问频率,返回False,继续执行self.throttled(request, throttle.wait(),向客户端返回还需要多少时间可以继续访问的提示。
if len(self.history) >= self.num_requests:
return self.throttle_failure()
#这里访问成功,返回True,继续执行dispatch。并把该条记录放到访问列表的头部,更新cache。
return self.throttle_success()