zoukankan      html  css  js  c++  java
  • Django Rest Framework --用户访问频率限制

    自定义访问频率控制类结构

    views.py

    from rest_framework.throttling import BaseThrottle
    import time
    # 节流
    visit_dict={}
    
    class Visitthrottle(BaseThrottle):
        #通过IP做唯一标识符
        #问题:非登陆用户一分钟内只允许访问3次
        def __init__(self):
            self.history=None
    
        def allow_request(self,request, view):
            #获取IP地址
            remote_addr = self.get_ident(request)
            ctime=time.time()
            if remote_addr not in visit_dict:
                visit_dict[remote_addr]=[ctime,]
                return True
            self.history = visit_dict.get(remote_addr)
            while self.history and self.history[-1] <ctime - 60:
                self.history.pop()
            if len(self.history)<3:
                self.history.insert(0,ctime)
                return True
    
        def wait(self):
            ctime=time.time()
            return 60-(ctime-self.history[-1])
    class TestThrottle(APIView):
        throttle_classes = [VisitThrottle,]
         
        def get(self, request, *args, **kwargs):
            pass
            '''
            等等一系列的视图功能方法
            '''

    实现原理分析:

    • 需要使用用户IP地址作为唯一标识符,如果使用用户登陆账号作为唯一标识符,一个用户可能拥有多个账号,则达不到节流的目的,但使用IP地址也不是说一定不能改变,但相比于登陆账号,使用IP地址更能达到节流的作用。
    •  以IP地址作为KEY键,多个访问时间形参列表作为value存入字典中,用户每次访问读取字典,判断最后一次访问时间与这次访问时间相差时间,相差时间大于60秒,删除时间列表中最后元素,然后判断列表长度是否小于3,如果小于3,表示一分钟内未访问3次,允许继续访问。
    • 如果不允许访问,会执行wait函数,返回需要等待时间。
    • 但是在项目开发中不使用自定义节流类,是因为drf中已经实现了节流方法。内置接口代码基本结构,内置节流类的实现原理与自定义节流类原理相同。

    内置节流类结构

    settings.py:

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThrottle',]
        'DEFAULT_THROTTLE_RATES': {
            '未认证用户': '10/m',
            '已认证用户': '100/h',
        },
    }
    

    mythrottle.py:

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import exceptions
    from rest_framework.throttling import SimpleRateThrottle
     
     
    class VisitThrottle(SimpleRateThrottle):
        scope = "未认证用户"
     
        def get_cache_key(self, request, view):
            return  self.get_ident(request)
           
     
    class UserThrottle(SimpleRateThrottle):
        scope = "已认证用户"
     
        def get_cache_key(self, request, view):
            return  request.user  # 认证通过后,认证方法authenticate的返回值之一<br><br>
    
    
    class TestThrottle(APIView):<br>  # 这样设置后,节流功能就会使用VisitThrottle类,而不会使用UserThrottle类
        throttle_classes = [VisitThrottle,]
         
        def get(self, request, *args, **kwargs):
            pass
            '''
            等等一系列的视图功能方法
            '''
    

      这里使用的节流类是继承了SimplePateThrottle类,而这个类利用了django内置的缓存来存储访问记录。通过全局节流设置,所有的视图类默认是使用UserThrottle类进行节流,如果不想使用默认的类就自定义给throttle_classes属性变量赋值,如:“throttle_classes = [VisitThrottle,]”。看到内置节流类的使用,可能一脸懵逼,下面进行源码分析。

    源码分析

    与之前认证权限控制的源码分析方法一致,先进入函数入口dispatch方法,封装完新的request对象后,进入initialize_request方法,我们会发现还有一个函数调用我们没有分析,所以这就是我们的节流函数。

    1.为什么会使用scope属性变量,有什么用?

    进入check_throttles函数,是否觉得很熟悉?没错在get_throttles方法中肯定也是一个列表生产式,返回一个有节流类实例组成的列表。

      

     在列表生成式中,先对内置类SimplePateThrottle进行实例化,在实例化中去拿到scope的值,并且根据值作为key值去配置文件中拿到对应value值。在parse_rate方法中可以看出value是又‘/’分隔的一个字符串。

      

    2.为什么会使用‘get_cache_key’方法,该方法的返回值是什么?

    实例化完成后,执行allow_request方法,首先执行的是get_cache_key’方法

     

    在get_cache_key’方法中里面什么都没写,所以就是说我们在使用内置节流类时,必须重构get_cacha_key方法,否则会抛出异常,因为内置节流类是通过django缓存实现,所以需要给它一个唯一标识符,在这里我选择的是选择用户的IP地址进行唯一确认,所以这里的返回值为一个唯一标识符。

     

    接下来的操作与我们自定义节流类的原理一致。最后如果返回false,调用wait方法,抛出异常

    3.为什么使用‘throttle_classes’属性变量,它有什么用?

    get_throttles方法返回的是一个列表生成式,而这里的throttle_classes就是在视图类TestThrottle中使用的,该变量就保存节流类对象。

     4.‘DEFAULT_THROTTLE_CLASSES’从那里来,有什么用?

    通过throttle_classes属性变量,跳转到该图,可以看到配置文件中说的“DEFAULT_THROTTLE_CLASSES”,它是用来通过配置文件settings来对全局节流类进行配置,功能等价于throttle_classes属性变量。

     5.‘DEFAULT_THROTTLE_RATES’从那里来,有什么用?

    由SimpleRateThrottle类和上文对scope属性变量的分析可知,DEFAULT_THROTTLE_RATES就是为了存储在配置文件中设置的不同的节流方法的。

     

    综上所述,可以看出,在利用内置节流接口时,通过配置文件settings的设置和提供该接口所需的用户唯一标识外,不需要我们做再多的操作,这就形成了我们上文写的内置接口代码基本结构的样式。

  • 相关阅读:
    www.insidesql.org
    kevinekline----------------- SQLSERVER MVP
    Sys.dm_os_wait_stats Sys.dm_performance_counters
    如何使用 DBCC MEMORYSTATUS 命令来监视 SQL Server 2005 中的内存使用情况
    VITAM POST MORTEM – ANALYZING DEADLOCKED SCHEDULERS MINI DUMP FROM SQL SERVER
    Cargo, Rust’s Package Manager
    建筑识图入门(初学者 入门)
    Tracing SQL Queries in Real Time for MySQL Databases using WinDbg and Basic Assembler Knowledge
    Microsoft SQL Server R Services
    The Rambling DBA: Jonathan Kehayias
  • 原文地址:https://www.cnblogs.com/kxsph/p/10572147.html
Copyright © 2011-2022 走看看