1. 程式人生 > >限流(訪問頻率)元件的使用

限流(訪問頻率)元件的使用

目錄

  • 限流(訪問頻率)元件的使用

限流(訪問頻率)元件的使用

框架中限流功能的實現依賴於封裝好的限流類,設定方式上分為全域性設定和區域性設定、繼承類設定和自定義類設定。如果要實現限流功能則必須設定DEAFULRT_THROTTLE_CLASSES和DEAFULRT_THROTTLE_RATES

自定義限流類

  • 限流類的基本思路:
  1. 限流需要知道訪問者的本地IP地址,通過地址才能進行記錄訪問次數;
  2. 限流需要了解訪問者訪問的時間,通過記錄時間和次數來限制規定時間內訪問者可以訪問的頻次;
  3. 拿到IP地址後,建立訪問記錄欄位,IP作為key,value是有訪問時的時間組成的列表,最近的訪問時間排在列表的左側,最早的訪問時間排在列表的右側,通過while迴圈,當最早的時間不符合規定的時間,通過pop()方法把最後一個從列表中剔除。
  4. 通過列表的長度來控制使用者訪問的次數,當滿足要求是把使用者訪問的時間插入到列表的下標為0的位置。
  5. wait方法主要功能是返回距離下次可以正常訪問的時間,注意返回值必須是數值,不能是字串,基本思路是:需要用當前時間減去被剔除的訪問時間得到的是剛過去多少時間,用限制的總時間再減去這個時間即可得到剩餘限制時間。

    Note
    需要注意兩點:
    1. 自定義的限流類中必須包含allow_request和wait方法,這兩個方法名不能寫錯,否則系統無法執行。
    2. 獲取IP地址的方法有兩種:
    • 方式一: remote_addr = request._request.META.get('REMOTE_ADDR')
    • 方式二: remote_addr = request.META.get('REMOTE_ADDR')
  • 自定義限流類程式碼:

      # 設定同一個IP一分鐘內只能訪問三次的限流功能
      import time
      VISIT_RECORD = {}
      class VisitThrottle(object):
          def __init__(self):
              self.history = None
              self.ctime = None
              self.time = None
              # 變數預設為空
          def allow_request(self, request, view):
              remote_addr = request._request.META.get('REMOTE_ADDR')
              # 獲取使用者IP
              # 如果繼承基類,那麼這個remote_addr = self.get_indent(request),直接呼叫繼承類中的方法
              ctime = time.time()
              self.ctime = ctime
              # 獲取當前時間
              if not remote_addr in VISIT_RECORD:
                  VISIT_RECORD[remote_addr] = [ctime,]
                  # 不存在記錄,建立記錄
              history = VISIT_RECORD.get(remote_addr)
              self.history = history
              while history and history[-1] < ctime - 60:
                  history.pop()
                  # 距離當前時間超過一分鐘的回自動剔除
              if len(history) <= 3:
                  history.insert(0, ctime)
                  return True
                  #返回True表示可以繼續訪問
    
          def wait(self):
              self.time = 60 - (self.ctime - self.history[-1])
              return self.time
              # 直接返回時間

全域性設定的實現

--settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':[
        'rest_framework.throttling.AnonRateThrottle',
        # 匿名使用者的限流
        'rest_framework.throttling.UserRateThrottle'
        # 註冊使用者的限流
    }    
    'DEFAULT_THROTTLE_RATES': {
        'anon': '2/minute',
        # 匿名使用者每分鐘限制訪問次數為5次
        'user': '5/minute',
        # 註冊使用者每分鐘限制訪問次數為15次
    }
--views.py
# 全侷限流功能的實現
class Demo5APIView(APIView):
    # 全域性設定不需要在檢視類中進行操作
    def get(self, request):
        # 投票頁面
        return Response('這是投票頁面')
--urls.py
    urlpatterns = [
        path('demo7/',views.Demo7APIView.as_view()),
        ]

區域性設定的實現

--settings.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'anon': '2/minute',
        # 匿名使用者每分鐘限制訪問次數為5次
        'user': '5/minute',
        # 註冊使用者每分鐘限制訪問次數為15次
    }
}
--views.py
# 區域性限流功能的實現
class Demo6APIView(APIView):
    throttle_classes = [UserRateThrottle, AnonRateThrottle]
    # 區域性設定需要寫在檢視函式中,以列表的形式來設定
    def get(self, reqeust):
        return Response('測試區域性限流功能')
--urls.py
urlpatterns =[
     path('demo6/', views.Demo6APIView.as_view()),
   ]

自定義限流功能的實現

--settings.py
'DEFAULT_THROTTLE_CLASSES': [
    'rest_framework.throttling.ScopedRateThrottle',
    # 自定義限流需要用到的類
    ],

'DEFAULT_THROTTLE_RATES': {
    'contacts': '5/hour',
    # 自定義限流的速率設定
    }
}
    

自定義限流功能的實現

--views.py
from rest_framework.throttling import ScopedRateThrottle
class Demo7APIView(APIView):
   throttle_scope = 'contacts'
   # 通過throttle_scope來設定限流速率名稱
   def get(self, request):
       return Response("測試自定義限流功能")
-- urls.py
urlpatterns = [
   path('demo7/', views.Demo7APIView.as_view()), 
  ]