DRF的限流组件(源码分析)
DRF限流组件(源码分析)
限流,限制用户访问频率,例如:用户1分钟最多访问100次 或者 短信验证码一天每天可以发送50次, 防止盗刷。
- 对于匿名用户,使用用户IP作为唯一标识。
- 对于登录用户,使用用户ID或名称作为唯一标识。
缓存={
用户标识:[12:33,12:32,12:31,12:30,12,] 1小时/5次 12:34 11:34
{
1. 配置缓存
# settings.py
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PASSWORD": "qwe123",
}
}
}
2. 自定义限流类
# -*- encoding:utf-8 -*-
# @time: 2023/4/21 15:41
# @author: ifeng
from django.core.cache import cache as default_cache
from rest_framework import exceptions
from rest_framework import status
from rest_framework.throttling import SimpleRateThrottle
class ThrottledException(exceptions.APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_code = 'throttled'
class MyRateThrottle(SimpleRateThrottle):
cache = default_cache # 访问记录存放在django的缓存中(需设置缓存)
scope = 'user' # 构造缓存中的key
cache_format = 'throttle_%(scope)s_%(ident)s'
# 设置其他访问评率, 例如: 一分钟允许访问10次
# 其他: 's': 'sec', 'm': 'min', 'h': 'hour', 'd': 'day'
THROTTLE_RATES = {'user': '10/m'}
def get_cache_key(self, request, view):
if request.user:
ident = request.user.id
else:
ident = self.get_ident(request) # 获取请求用户IP(request中找请求头)
# throttle_u # throttle_user_11.11.11.11ser_2
return self.cache_format % {'scope': self.scope, 'ident': ident}
def throttle_failure(self):
wait = self.wait()
detail = {
'code': 1005,
'data': '访问频率限制',
'detail': '需要等待 %s s才能访问' % (int(wait))
}
raise ThrottledException(detail)
3. 使用限流类
- 局部配置(views)
class UserView(APIView):
throttle_classes = [MyRateThrottle, ] # 限流
- 全局配置(settings)
REST_FRAMEWORK = {
# 限流
"DEFAULT_THROTTLE_CLASSES": ["app01.throttle.MyRateThrottle", ],
"DEFAULT_THROTTLE_RATES": {
"user": "10/m",
# "xx":"100/h"
}
}
4. 多个限流类
本质,每个限流的类中都有一个 allow_request 方法,此方法内部可以有三种情况:
- 返回True,表示当前限流类允许访问,继续执行后续的限流类。
- 返回False,表示当前限流类不允许访问,继续执行后续的限流类。所有的限流类执行完毕后,读取所有不允许的限流,并计算还需等待的时间。
- 抛出异常,表示当前限流类不允许访问,后续限流类不再执行。
5. 源码分析
- 这是限流大体的执行逻辑, 后面将对allow_reqeust中具体分析

- allow_request()在自定义的类里面没定义, 所以我们到父类SimpleRateThrottle执行allow_request()方法

DRF的限流组件(源码分析)的更多相关文章
- alibaba sentinel限流组件 源码分析
如何使用? maven引入: <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>s ...
- 面试官:来谈谈限流-RateLimiter源码分析
RateLimiter有两个实现类:SmoothBursty和SmoothWarmingUp,其都是令牌桶算法的变种实现,区别在于SmoothBursty加令牌的速度是恒定的,而SmoothWarmi ...
- Django框架之drf:8、断点调试,权限、认证、频率组件源码分析,基于APIView编写分页,异常处理
Django框架之drf 一.断点调式使用 指,在我们编写代码的时候,程序运行出现报错是无可避免的,当程序 出现报错时,我们需要找到出现报错的代码进行修改,如果时简短的代码很容易就可以找到报错位置 ...
- Django-restframework 源码之认证组件源码分析
Django-restframework 源码之认证组件源码分析 一 前言 之前在 Django-restframework 的流程分析博客中,把最重要的关于认证.权限和频率的方法找到了.该方法是 A ...
- element-ui 组件源码分析整理笔记目录
element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...
- ceph-csi组件源码分析(1)-组件介绍与部署yaml分析
更多ceph-csi其他源码分析,请查看下面这篇博文:kubernetes ceph-csi分析目录导航 ceph-csi组件源码分析(1)-组件介绍与部署yaml分析 基于tag v3.0.0 ht ...
- 开源MyBatisGenerator组件源码分析
开源MyBatisGenerator组件源码分析 看源码前,先了解Generator能做什么? MyBatisGenerator是用来生成mybatis的Mapper接口和xml文件的工具,提供多种启 ...
- element-ui button组件 radio组件源码分析整理笔记(一)
Button组件 button.vue <template> <button class="el-button" @click="handleClick ...
- element-ui MessageBox组件源码分析整理笔记(十二)
MessageBox组件源码,有添加部分注释 main.vue <template> <transition name="msgbox-fade"> < ...
- Django REST framework —— 权限组件源码分析
在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...
随机推荐
- HashMap记录
1.HashMap接收null的键值 2.HashMap是非synchronized的 3.HashMap使用hashCode找到bucket的位置.bucket中存储的是键和值 4.当HashCod ...
- idea中新建java类
project是项目,一个大目录,里面可以放多个module project里面存放: .idea文件(project相当于workplace) module(模块) out(编译生成的.class文 ...
- vs2013安装完VASSISTX助手之后字体变成斜体如何解决?
VC助手为最新版本. 1. 打开vc助手选项 2. 取消勾选"show stable symbols in italics"
- 整数划分问题(Java递归)
整数划分问题(Java递归) 文章目录 整数划分问题(Java递归) 0. 问题描述 1.递归式 2.代码 3.参考 0. 问题描述 整数划分问题 将正整数n表示成一系列正整数之和:n=n1+n2+- ...
- 统信桌面端专业版开启cron日志,确认定时任务执行情况
默认没有开启cron日志记录 1. 修改rsyslog vi /etc/rsyslog.conf #将cron前面的注释符去掉 cron.* /var/log/cron.log 排查完毕需关闭,重新注 ...
- Adams:一种使接触力(力矩等等)失效的方法
1 第一步:点击"运行脚本". 2 第二步:右击选择"仿真脚本",点击"创建". 3 第三步:选择"脚本类型"为&quo ...
- C++ accumulate()函数的用法
accumulate定义在 numeric 中,作用有两个,一个是累加求和,另一个是自定义类型数据的处理. 头文件 #include <numeric> 原型 默认求累加和 templat ...
- 在MDK 5中打开MDK 4工程要注意的问题1
我是生手,对于MDK的理解还很简单.以下内容是遇到的一种情况. 有一个MDK 4工程,要求顺序点亮4个LED灯,工程已经建好. 在MDK 5中打开,编译都没问题,要烧写时,提示"can no ...
- 第二章启动引导器GRUB2
第二章启动引导器GRUB2grub的配置文件路径:vim /boot/grub2/grub.cfg (不建议直接编辑)vim /etc/default/grub (可编辑的文件)将编辑的操作刷新到/b ...
- database.property文件
注意修改用户名密码 mysql8的版本要注意配置时区 此文件放置连接数据库的相关参数 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://l ...