07 drf源码剖析之节流
07 drf源码剖析之节流
1. 节流简述
节流类似于权限,它确定是否应授权请求。节流指示临时状态,并用于控制客户端可以向API发出的请求的速率。
还有情况可能是 ,由于某些服务特别耗费资源,因此您需要在API的不同部分施加不同的约束。
频率限制在认证、权限之后
2. 节流使用
在settings配置文件中设置规定时间段内可以访问的次数
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_RATES": {"anon": '10/m'},
}
在需要节流的类中加throttle_classes
from rest_framework.views import APIView
from rest_framework.response import Response from rest_framework.throttling import AnonRateThrottle,BaseThrottle class ArticleView(APIView):
throttle_classes = [AnonRateThrottle,]
def get(self,request,*args,**kwargs):
return Response('文章列表') class ArticleDetailView(APIView):
def get(self,request,*args,**kwargs):
return Response('文章列表')
3. 源码剖析
请求过来先执行dispatch方法
class APIView(View):
permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES def dispatch(self, request, *args, **kwargs):
# 封装request对象...
self.initial(request, *args, **kwargs)
# 通过反射执行视图中的方法...
initial方法过渡
def initial(self, request, *args, **kwargs):
# 版本的处理...
# 认证...
# 权限判断 self.check_throttles(request) # 节流
将所有的节流类实例化成对象列表
def get_throttles(self):
return [throttle() for throttle in self.throttle_classes]
循环执行每个对象的allow_request方法
def check_throttles(self, request):
throttle_durations = []
for throttle in self.get_throttles():
if not throttle.allow_request(request, self):
throttle_durations.append(throttle.wait())
执行allow_request方法,AnonRateThrottle没有allow_request,去父类找
class AnonRateThrottle(SimpleRateThrottle):
scope = 'anon' def get_cache_key(self, request, view):
if request.user.is_authenticated:
return None # Only throttle unauthenticated requests. return self.cache_format % {
'scope': self.scope,
'ident': self.get_ident(request)
}
执行SimpleRateThrottle类中allow_request方法
- 获取请求用户的IP
- 根据IP获取他的所有访问记录
- 获取当前时间
- 将不在规定时间的记录删除掉
- 判断规定时间段时间内访问了多少次
- 和设定次数对比,判断用户是否可以继续访问
class SimpleRateThrottle(BaseThrottle):
cache = default_cache
timer = time.time
cache_format = 'throttle_%(scope)s_%(ident)s'
scope = None
THROTTLE_RATES = api_settings.DEFAULT_THROTTLE_RATES def __init__(self):
if not getattr(self, 'rate', None):
self.rate = self.get_rate()
self.num_requests, self.duration = self.parse_rate(self.rate) def parse_rate(self, rate):
if rate is None:
return (None, None)
num, period = rate.split('/')
num_requests = int(num)
duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
return (num_requests, duration) def allow_request(self, request, view):
if self.rate is None:
return True # 获取请求用户的IP
self.key = self.get_cache_key(request, view)
if self.key is None:
return True # 根据IP获取他的所有访问记录,[]
self.history = self.cache.get(self.key, []) self.now = self.timer() while self.history and self.history[-1] <= self.now - self.duration:
self.history.pop()
if len(self.history) >= self.num_requests:
return self.throttle_failure()
return self.throttle_success() def throttle_success(self):
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
return True def throttle_failure(self):
return False def wait(self):
if self.history:
remaining_duration = self.duration - (self.now - self.history[-1])
else:
remaining_duration = self.duration available_requests = self.num_requests - len(self.history) + 1
if available_requests <= 0:
return None return remaining_duration / float(available_requests)
总结:
- 实现原理
来访问时:
1.获取当前时间 100121280
2.100121280-60 = 100121220,小于100121220所有记录删除
3.判断1分钟以内已经访问多少次了? 4
4.无法访问
停一会
来访问时:
1.获取当前时间 100121340
2.100121340-60 = 100121280,小于100121280所有记录删除
3.判断1分钟以内已经访问多少次了? 0
4.可以访问 - 具体流程
- 请求来时会执行allow_follow方法,
- 会用self.key获取请求用户的ip,再用self.history根据用户的ip获取其访问的记录,
- 获取当前的时间,用当前的时间减去设定的时间段,
- 循环该用户访问的记录,将不在该时间段的记录pop掉,
- 通过len判定该时间段已经访问了多少次,超过限定次数会返回false
- 匿名用户是通过ip进行访问限制,登录用户通过用户的id进行访问限制
07 drf源码剖析之节流的更多相关文章
- drf源码剖析系列(系列目录)
drf源码剖析系列(系列目录) 01 drf源码剖析之restful规范 02 drf源码剖析之快速了解drf 03 drf源码剖析之视图 04 drf源码剖析之版本 05 drf源码剖析之认证 06 ...
- 06 drf源码剖析之权限
06 drf源码剖析之权限 目录 06 drf源码剖析之权限 1. 权限简述 2. 权限使用 3.源码剖析 4. 总结 1. 权限简述 权限与身份验证和限制一起,决定了是否应授予请求访问权限. 权限检 ...
- 05 drf源码剖析之认证
05 drf源码剖析之认证 目录 05 drf源码剖析之认证 1. 认证简述 2. 认证的使用 3. 源码剖析 4. 总结 1. 认证简述 当我们通过Web浏览器与API进行交互时,我们可以登录,然后 ...
- 04 drf源码剖析之版本
04 drf源码剖析之版本 目录 04 drf源码剖析之版本 1. 版本简述 2. 版本使用 3.源码剖析 4. 总结 1. 版本简述 API版本控制使您可以更改不同客户端之间的行为.REST框架提供 ...
- 02 drf源码剖析之快速了解drf
02 drf源码剖析之快速了解drf 目录 02 drf源码剖析之快速了解drf 1. 什么是drf 2. 安装 3. 使用 3. DRF的应用场景 1. 什么是drf drf是一个基于django开 ...
- 07 flask源码剖析之用户请求过来流程
07 Flask源码之:用户请求过来流程 目录 07 Flask源码之:用户请求过来流程 1.创建ctx = RequestContext对象 2. 创建app_ctx = AppContext对象 ...
- drf源码分析系列---节流(访问频率限制)
使用 from rest_framework.throttling import AnonRateThrottle from rest_framework.generics import ListAP ...
- 01 drf源码剖析之restful规范
01 restful规范 目录 01 restful规范 1. 什么是restful规范 2.restful规范详细 1. 什么是restful规范 restful是一套规则,是程序间进行数据传输的一 ...
- DRF源码系列分析
DRF源码系列分析 DRF源码系列分析--版本 DRF源码系列分析--认证 DRF源码系列分析--权限 DRF源码系列分析--节流
随机推荐
- filebeat v6.3 多行合并的步骤 多个表达式同时匹配
配置文件位于/etc/filebeat/filebeat.yml,就是filebeat的主配置文件打开文件filebeat.yml,搜索multiline:,默认是注释的,常用的有如下三个配置: mu ...
- IOS 发布 程序截图问题
特别要注意那个有无状态栏时的像素要求 **注意:在截屏模拟器的时候,请把模拟器的Scale设置成100%(Window->Scale->100%) 开模拟器截图,运行每一个iOS型号,然后 ...
- 如何解析json格式的字符串
package com.json; import java.util.ArrayList; import java.util.HashMap; import java.util.List; impor ...
- jmeter录制app测试脚本
1.jmeter 下载地址 https://jmeter.apache.org 2.选择下载包 3.下载完成后解压即可使用(也可以配置环境变量,但我一般不配置,可以使用) 4.打开jmeter 创建线 ...
- 使用matplotlib进行可视化
转自:https://blog.csdn.net/qq_30614345/article/details/99049790 https://blog.csdn.net/qq_30614345/arti ...
- 龙芯团队完成CoreCLR MIPS64移植,在github开源
国产龙芯的软件生态之中.NET不会缺席,毕竟 C# 与 .NetCore/Mono 也是全球几大主流的编程语言和运行平台之一,最近一段时间听到太多的鼓吹政务领域不支持.NET, 大家都明白这是某些人为 ...
- linux kernel update
linux内核升级 最近HW行动,报出来的linux系统内核漏洞,环境中全部是2.6.32-431.el6.x86_64的主机,需要全部升级到754版本,这也是第一次进行内核升级操作. 先找了一台和生 ...
- pick靶场-sql注入
甲.数字型注入 数字型注入一般提交值没有引号,所以直接在后面构造语句就可以了. 抓包查看 构造语句 提交后 该数据库表内容被爆出来了. 乙.字符型注入 首先我们要知道一点,字符串在数据库中提交是需要用 ...
- SDL软件安全读书笔记(一)
# 如何应对当前的全球网络安全威胁? 开发安全漏洞尽可能少的软件,应该着眼于源头安全. 边界安全盒深度防御是重要的安全手段,但软件自身的安全是安全防护的第一关. 即使软件源头存在较少的漏洞,这些漏洞也 ...
- vue中使用element2
阻止谷歌下记住密码 当我们将input框的类型设置为密码框的时候,就会出现下面这种效果,不仅样式不统一,有的时候,密码框的上面并不是用户名,而是其他的内容,也会被强制显示为用户名: 首先需要解决样式问 ...