45.限流Throttling及源碼解析( 三 )

UserRateThrottle認證用戶限流類:繼承了SimpleRateThrottle,僅僅是重寫了 get_cache_key 方法UserRateThrottle 用于限制已認證的用戶在整個API中的請求頻率 。用戶ID用于生成唯一的密鑰 。未經身份驗證的請求將使用傳入的請求的IP地址生成一個唯一的密鑰允許的請求頻率由以下各項之一確定(按優先順序):

  1. 類的 rate 屬性,可以通過繼承 UserRateThrottle 并設置該屬性來修改這個值,優先級高
  2. settings配置文件中 DEFAULT_THROTTLE_RATES['user'] 配置項的值 。優先級低
# 設置頻率控制的key位anonscope = 'user'# 重寫get_cache_key方法def get_cache_key(self, request, view):if request.user.is_authenticated:# 如果請求用戶是認證用戶,設置用戶的唯一標識賦值給identident = request.user.pkelse:#如果請求用戶是非認證用戶 , 通過get_ident獲取請求ip賦值給identident = self.get_ident(request)# 設置SimpleRateThrottle中self.cache_format的值return self.cache_format % {'scope': self.scope,'ident': ident}ScopedRateThrottle用戶對于每個視圖的訪問頻次:繼承了SimpleRateThrottle , 重寫了 get_cache_key 和allow_request 方法ScopedRateThrottle 類用于限制對APIs特定部分的訪問,也就是視圖級別的限流,不是全局性的只有當正在訪問的視圖包含 throttle_scope 屬性時 , 才會應用此限制 。然后,通過將視圖的“scope”屬性值與唯一的用戶ID或IP地址連接,生成唯一的密鑰 。允許的請求頻率由 scope 屬性的值在 DEFAULT_THROTTLE_RATES 中的設置確定class ScopedRateThrottle(SimpleRateThrottle):scope_attr = 'throttle_scope'def __init__(self):passdef allow_request(self, request, view):#從view獲取self.scope_attr賦值給scope , 如果view中沒有指定,設置為Noneself.scope = getattr(view, self.scope_attr, None)# 如果沒有設置scope,直接返回Trueif not self.scope:return True# 獲取settings頻率設置限流類對應的keyself.rate = self.get_rate()# 獲取頻率限制、持續時長self.num_requests, self.duration = self.parse_rate(self.rate)# 調用父類的allow_request 返回對應的結果return super().allow_request(request, view)# 獲取用戶唯一標識def get_cache_key(self, request, view):# 如果是認證用戶 ident=用戶唯一標識if request.user.is_authenticated:ident = request.user.pkelse:# 非認證用戶返回請求的ipident = self.get_ident(request)# 設置父類的類屬性return self.cache_format % {'scope': self.scope,'ident': ident} 自定義限流類上面源碼的類,我們一般使用的是后三個,如果源碼提供的限流類無法滿足我們的需求,我們可以寫自定義的限流類自定義限流類的步驟:
  1. 繼承BaseThrottle類或者根據場景繼承其他限流類
  2. 實現allow_request方法,如果請求被允許,那么返回True,否則返回False
  3. wait方法,是否實現根據自己場景
  4. 獲取唯一標識的方法可以使用源碼自由的,也可以自定義
  場景案例1假設我們的請求需要同時進行多個認證用戶的限流措施,比如每小時限制100次,同時每天限制1000次# 每小時的限流類class UserHourRateThrottle(UserRateThrottle):scope = 'userHour'# 每天的限流類class UserDayRateThrottle(UserRateThrottle):scope = 'userDay' # settings中進行配置REST_FRAMEWORK = {'DEFAULT_THROTTLE_CLASSES': (# 配置我們自定義的限流類或者再view中進行局部的配置'testApi.throttles.UserHourRateThrottle','testApi.throttles.UserDayRateThrottle'),'DEFAULT_THROTTLE_RATES': {'userHour': '100/hour', # 每小時最多100次'userDay': '1000/day' # 每天最多100次}}場景案例2隨機限制import randomclass RandomRateThrottle(throttling.BaseThrottle):def allow_request(self, request, view):# 如果隨機的數字 不等于1,返回True,否則返回Falsereturn random.randint(1, 10) != 1# 之后在settings進行配置或者局部配置
45.限流Throttling及源碼解析

文章插圖
【45.限流Throttling及源碼解析】

推薦閱讀