Rest Framework之节流(用户访问次数/评率限制)的使用和源码流程

节流(用户访问次数/频率限制)

  理解:用户疯狂访问API,占用、消耗大量资源,通过使用节流限制(例如每分钟)的访问频率,有效缓解服务器压力。

节流的方法有很多:基于用户IP限制访问频率、view中限制请求频率、匿名时用IP限制、登录时用Token限制等。

一、节流的基本使用

  自定义一个类来做实现节流规则,此类中必须要实现两个方法:allow_request、wait。并推荐继承BaseThrottle。

 

    allow_request中是节流的规则,wait是被限制后需要等待的时间。默认可以不做任何操作

  1、url

 

1 from django.urls import path
2 from api import views
3 
4 urlpatterns = [
5     path('TestView/', views.TestView.as_view()),
6 ]

 

  2、节流规则自定义的类

 1 from rest_framework.throttling import BaseThrottle
 2 
 3 
 4 VISIT_RECORD = {}
 5 
 6 
 7 class MyThrottles(BaseThrottle):
 8 
 9     def __init__(self):
10         self.history = None
11 
12     def allow_request(self, request, view):
13         # 1、获取用户IP
14         # remote_addr = request._request.META.get('REMOTE_ADDR').----->request._request.META.get====request.META.get
15         # remote_addr = self.get_ident(request)父类里面这个方法也是获取IP,可以直接用
16         remote_addr = request.META.get('REMOTE_ADDR')
17         ctime = time.time()
18         if remote_addr not in VISIT_RECORD:
19             VISIT_RECORD[remote_addr] = [ctime, ]
20             # print(remote_addr)
21             return True
22         history = VISIT_RECORD.get(remote_addr)
23         self.history = history
24         while history and history[-1] < ctime - 10:
25             history.pop()
26         if len(history) < 3:
27             history.insert(0, ctime)
28             return True
29         # return True  # return False 表示访问频率太高,限制访问
30 
31     def wait(self):
32         '''
33         等待时间显示
34         :return:
35         '''
36         ctime = time.time()
37         return 60 - (ctime - self.history[-1])
throttle

   

 1 class TestView(APIView):
 2 
 3     # throttle_classes = [VisitThrottles, ]
 4 
 5     def get(self, request, *args, **kwargs):
 6         # self.dispatch
 7         return Response("GET,请求")
 8 
 9     def post(self, request, *args, **kwargs):
10         pass
11 
12     def put(self, request, *args, **kwargs):
13         pass
14 
15     def delete(self, request, *args, **kwargs):
16         pass
View

    局部视图认证

      TestView是后端响应内容,在需要认证的后端响应视图中加上类变量

        throttle_classes = [VisitThrottles, ]

       加上后,此视图的所有操作均执行这个这个节流规则

    全局视图认证(此项目中所有类均自动使用认证规则)

      将写认证规则写在一个单独的PY文件中,

      配置settings.py,其中“web.utils”是文件的调用路径

1 REST_FRAMEWORK = {
2     "DEFAULT_THROTTLE_CLASSES": ["api.utils.throttle.VisitThrottles"],
3     }
4 }
全局调用配置文件

 

二、节流的源码流程

   1、请求流程第一步,一样是通过进入到dispatch,走到initial中

       

  2、我们从上到下,我们已经都依次看到了,认证、权限。第三个就是咱们的访问频率的限制

                          

  3、来看看这个方法里面做了些什么,

    3.1、我们看到了循环语句,这里根据以前的经验,get_throttles里面应该是一个列表生成式,将每一个节流规则类的对象生成,并构成列表

      列表生成式中的节流规则类,则应该是来自throttle_classes变量中,而此变量里面则存放的是配置文件。当我们在局部使用时,可以在类中定义

      类字段throttle_classes,如果全局使用,则在配置文件,REST_FRAMWORK变量中定义

    3.2、循环拿到每一个节流规则类的对象后,需要去执行allow_request方法,所以,我们在自定义节流规则类的时候,必须要实现这个方法

      如果执行allow_request方法返回了false,则需要执行每个自定义节流规则类的wait方法,所以这个方法我我们也必须要实现。

       

    3.3、果然,get_throttles方法内部就是列表生成式和throttle_classes变量,配置文件的定义

      

       

  4、当我们熟悉了前面的认证、权限流程,节流的流程就显得很简单了

 

三、内置的节流规则

    我们自定义的节流规则,利用用户访问时带过来的IP地址做限制标识,在rest_framework中有内置的节流规则类,和我们的思路是一样的

    我们可以直接使用,内置节流规则SimpleRateThrottle,我们可以继承它,来完成,功能实现。一起来看看他的源码和我们的是一样吗。

1 class VisitThrottles(SimpleRateThrottle):
2     scope = "Luffy"
3 
4     def get_cache_key(self, request, view):
5         return self.get_ident(request)

  1、我们在源码流程中知道,要实现节流的限制,必须要实现allow_request方法和wait方法,查看SimpleRateThrottle看看也确实现了这两种方法

      

  2、首先这个内置的节流规则类已经可以完成基本的要求,那么我们再来详细看看他的实现过程,首先,在此类中的inint构造方法中,通过反射执行了get_rate方法,

    查看此方法,发现,我们在使用这个内置规则是,要求我们必须要声明scope类变量,通过此变量来寻找配置文件中限制的规则。意思是可以通过用户自定义限制频率,

    例如:用户要求的访问频次为每分钟访问10次。那么我们在配置文件中设置【"test":"10/m"】,那么怎么才能知道用户设置的频次呢,就是通过“test”这个标识来寻找

    所以,此时设置的scope="test"

    当然一般都是在配置文件,不可能每次都来修改源码文件。

    

    2.1、可以通过设置不同的变量来满足不同视图的访问频次

      

  3、继续往下看构造方法还干了什么。执行了parse_rate方法,并把获取到的类变量scope的值封装在self.rate传了进去。很明显返回了两个值。

    看看parse_rate方法,中,将获取到的值,以‘/’作为分割出来了,下面并通过对应的字符串的首字母来进行时间的划分,查看用户是以天、时、分、秒来作为划分的

    并且返回了,两个值,第一个是频次,第二个是时间单位对应的秒数。看到这里我们就要明白,用户在书写频率的时候,必须要按照“数字/时间单位”这中形式,不然无法划分识别。

    

  4、通过前面的源码流程,我们知道当请求进来,通过了,认证、权限,下一步走节流限制,进入源码流程实例化了节流规则类的对象后,第一个执行的就是方法是allow_request

    那我们在看看内置规则中的allow_request。

    

 

      4.1、回头看,我们继承此方法时,所必须写的方法。这里执行了,get_ident方法,通过前面,我们知道这个方法,是获取IP作为标识来做节流限制的。

          查看的方法,通过类的继承去一层一层找吧

        

  5、通过用户设定的访问频率和标识,使用完全内置的方法来做节流规则。

    

 

 

 

  6、通过完全内置的方法,我们只需要写4行代码即可实现,节流功能。

 

  7、匿名用户,通过get_ident方法来获取IP作为标识,做节流限制。登录用户我们可以用token来进行限制

    我们需要做的只是在继承的类中,重写我们的get_ident方法。获取缓存中,用户登录后的token,即可。

    

 

 

    

 

posted @ 2019-04-30 15:45  cunzhishu  阅读(281)  评论(0)    收藏  举报