drf源码分析系列---节流(访问频率限制)

使用

from rest_framework.throttling import AnonRateThrottle
from rest_framework.generics import ListAPIView,CreateAPIView,UpdateAPIView,DestroyAPIView,RetrieveAPIView
from api.serializer.articleserializer import ArticleSerializer
from api import models
class ArticleAPIView(ListAPIView):
    authentication_classes = []
    throttle_classes = [AnonRateThrottle, ] #给改类设置频率限制,当访问改视图对应的路由时会有频率限制
    queryset = models.Article.objects.all()
    serializer_class = ArticleSerializer
setting.py频率限制
REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_RATES":{
        "anon":'10/m' #1分钟访问3次
    }
}

节流的原理

当我们请求进来,走到我们频率组件的时候,DRF内部会有一个字典来记录访问者的IP,
	以这个访问者的IP为key,value为一个列表,存放访问者每次访问的时间,
	# { IP1: [第三次访问时间,第二次访问时间,第一次访问时间],}
	把每次访问最新时间放入列表的最前面,记录这样一个数据结构后,通过什么方式限流呢~~

如果我们设置的是10秒内只能访问5次,
  1,判断访问者的IP是否在这个请求IP的字典里
  2,保证这个列表里都是最近10秒内的访问的时间
     判断当前请求时间和列表里最早的(也就是最后的)
      如果差大于10秒,说明请求以及不是最近10秒内的,删除掉,继续判断倒数第二个,直到差值小于10秒
  3,判断列表的长度(即访问次数),是否大于我们设置的5次,
     如果大于就限流,否则放行,并把时间放入列表的最前面

节流的源码分析

执行流程

1.请求进来执行dispatch方法中的initialize_request方法
    def initialize_request(self, request, *args, **kwargs):
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    
2.执行inital
    def initial(self, request, *args, **kwargs):
		.......略过的代码
        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)  #节流函数
3.执行check_throttles(request)函数
    def check_throttles(self, request):
        throttle_durations = []
        for throttle in self.get_throttles():
            if not throttle.allow_request(request, self):
                throttle_durations.append(throttle.wait())

	3.1get_throttles函数
    def get_throttles(self):
        return [throttle() for throttle in self.throttle_classes]
	3.2执行allow_request(request, self)
4.然后就执行了节流的原理的逻辑代码

posted @ 2019-11-22 20:12  corei5tj  阅读(158)  评论(0编辑  收藏  举报