開發平臺的API接口調用須要限制其頻率,以節約服務器資源和避免惡意的頻繁調用.服務器
DRF就爲咱們提供了一些頻率限制的方法.
DRF中的版本、認證、權限、頻率組件的源碼是一個流程,且頻率組件在最後執行.數據結構
@ide
DRF頻率組件原理
·
DRF中的頻率控制基本原理是基於訪問次數和時間的,固然咱們也能夠經過本身定義的方法來實現.
當請求進來,走到咱們的頻率組件時,DRF內部會有一個字典來記錄訪問者的IP.
以這個字典的IP爲key,value爲一個列表,存放訪問者每次訪問的時間:{PI1: [第三次訪問時間, 第二次訪問時間, 第一次訪問時間, ]}
把每次訪問的最新時間放入列表的最前面,記錄這樣一個數據結構後,經過以下方式限制:
·
若是咱們設置的是10秒內只能訪問5次:測試
- 判斷訪問者的IP是否在這個請求IP的字典裏.
- 保證這個列表裏都是都是最近10秒內訪問的時間.
: 判斷當前請求時間和列表裏最先的(也就是最後一個)請求時間差
: 若是差大於10秒,說明請求不是最近10秒內的,刪除掉最後一個
: 繼續判斷倒數第二個、第三個,直到差小於10秒爲止- 判斷列表的長度(即訪問次數)是否大於咱們設置的5次.
: 若是大於,則限制其訪問
: 若是小於,則放行,並把時間記錄到列表的最前面
首先 配置頻率限制類spa
from rest_framework.throttling import SimpleRateThrottle # 導入內置的頻率限制類 class DRFThrottle(SimpleRateThrottle): """注意:這裏都是必備的屬性、方法和返回值""" scope = 'WD' def get_cache_key(self, request, view): # 拿IP地址 return self.get_ident(request)
而後 配置文件3d
REST_FRAMEWORK = { # 指定頻率限制的類 "DEFAULT_THROTTLE_CLASSES": ['blog.throttle.DRFThrottle'], # WD是scope定義的值,3/m表示每分鐘不能超過3次訪問 "DEFAULT_THROTTLE_RATES": {"WD": "3/m"}, } """ 若是隻是想給單個視圖作頻率限制: 則刪除這裏的"DEFAULT_THROTTLE_CLASSES"配置項 並在要作頻率限制的視圖中指定頻率限制類便可 指定語法:throttle_classes = ["頻率限制類", ] """
開始測試rest
訪問測試頁面,連續刷新3次後,可看到:
blog
首先 自定義頻率限制類接口
import time VISIT_RECORD = {} # 限制訪問次數的字典 class MyThrottle(): """ 自定義頻率限制類,一分鐘容許訪問5次 注意:自定義頻率限制類中必需要有allow_request和wait方法 前者用於頻率限制的邏輯,後者用於返回限制時間還剩多少秒 """ def __init__(self): self.history = [] def allow_request(self, request, view): """用於限制訪問的邏輯""" # 獲取用戶的IP地址 ip = request.META.get('REMOTE_ADDR') if ip not in VISIT_RECORD: VISIT_RECORD[ip] = [time.time(), ] else: history = VISIT_RECORD[ip] self.history = history history.insert(0, time.time()) # 確保訪問時間在容許範圍以內 while self.history[0] - self.history[-1] > 60: self.history.pop() # 肯定訪問次數在容許的範圍內 if len(self.history) >= 5: return False return True def wait(self): """用於返回限制時間還剩多少秒""" return 60 - (self.history[0] - self.history[-1])
而後 配置文件圖片
REST_FRAMEWORK = { # 指定自定義的頻率限制類 "DEFAULT_THROTTLE_CLASSES": ['blog.throttle.MyThrottle'], } > """ 若是隻是想給單個視圖作頻率限制: 則刪除這裏的"DEFAULT_THROTTLE_CLASSES"配置項 並在要作頻率限制的視圖中指定頻率限制類便可 指定語法:throttle_classes = ["頻率限制類", ] """
好了,就到這裏吧.