限流(訪問頻率)組件的使用
框架中限流功能的實現依賴於封裝好的限流類,設置方式上分為全局設置和局部設置、繼承類設置和自定義類設置。如果要實現限流功能則必須設置DEAFULRT_THROTTLE_CLASSES和DEAFULRT_THROTTLE_RATES
自定義限流類
- 限流類的基本思路:
- 限流需要知道訪問者的本地IP地址,通過地址才能進行記錄訪問次數;
- 限流需要了解訪問者訪問的時間,通過記錄時間和次數來限制規定時間內訪問者可以訪問的頻次;
- 拿到IP地址后,創建訪問記錄字段,IP作為key,value是有訪問時的時間組成的列表,最近的訪問時間排在列表的左側,最早的訪問時間排在列表的右側,通過while循環,當最早的時間不符合規定的時間,通過pop()方法把最后一個從列表中剔除。
- 通過列表的長度來控制用戶訪問的次數,當滿足要求是把用戶訪問的時間插入到列表的下標為0的位置。
- wait方法主要功能是返回距離下次可以正常訪問的時間,注意返回值必須是數值,不能是字符串,基本思路是:需要用當前時間減去被剔除的訪問時間得到的是剛過去多少時間,用限制的總時間再減去這個時間即可得到剩余限制時間。
Note
需要注意兩點:
- 自定義的限流類中必須包含allow_request和wait方法,這兩個方法名不能寫錯,否則系統無法運行。
- 獲取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()),
]