什么是限流?
- 限流类似于权限机制,它也决定是否接受当前请求,用于控制客户端在某段时间内允许向API发出请求的次数 , 也就是频率
- 假设有客户端(比如爬虫程序)短时间发起大量请求,超过了服务器能够处理的能力,将会影响其他用户的正常使用
- 为了保证服务的稳定性,并防止接口受到恶意用户的攻击 , 我们可以对接口进行限流
- 又或者可以对未经身份验证的请求设置访问频率,对经过身份验证的请求不限制访问频率
- 限流也不止单指限制访问次数的措施,例如付费数据服务的特点访问次数
- 区分用户场景,比如匿名和已登录,不同权限的用户不同的限流策略
- API的不同,根据不同API设置不同的策略
- 请求的爆发期和持续期不同的限流策略
- 可以同时支持使用多个限流策略
REST_FRAMEWORK = {# 全局限流类的配置'DEFAULT_THROTTLE_CLASSES': ('rest_framework.throttling.AnonRateThrottle',# 对于匿名用户的限流'rest_framework.throttling.UserRateThrottle' #对于登录用户的限流),# 限流频率的配置'DEFAULT_THROTTLE_RATES': {'anon': '100/day', # 未认证用户一天只许访问100次'user': '1000/day' # 认证用户一天可以访问1000次}}
DEFAULT_THROTTLE_RATES设置限流频率格式 次数/时间单位- second: 按秒设置频率次数
- minute:按分钟设置频率次数
- hour:按小时设置频率次数
- day: 按天设置频率次数
#导入限流模块from rest_framework import throttling class getInfoList(ModelViewSet):# 通过throttle_classes 设置该视图的限流类# 视图指定会覆盖settings设置的全局限流throttle_classes = (throttling.UserRateThrottle,)def infoList(self):...
识别请求的客户端我们既然要对请求进行限流,那么肯定要失识 别是谁发来的请求,然后进行对应的措施,不然无法确定请求者身份,那么就无法得知是不是需要限制的请求,常见的方法有三种- drf利用http报头的 x-forwarded-for 或者wsgi中的remote-addr变量来唯一标识客户端的IP地址
- 如果 存在x-forwarded-for 属性,则使用x-forwarded-for ,否则使用remote-addr
- 可以使用request.user的属性来标识请求,比如使用request.user.id 来标记唯一请求
- 使用IP地址对客户端请求进行限流,需要考虑使用伪造代理IP请求的情况
- BaseThrottle: 限流基类
- SimpleRateThrottle:频率校验类
- AnonRateThrottle:匿名用户限流
- UserRateThrottle:认证用户限流
- ScopedRateThrottle:api视图级别的限流
class BaseThrottle:# allow_request源码并没有直接实现功能,只是写好了方法占位,待后续继承实现# 该方法主要是处理是否允许请求通过# 如果后续继承基类实现该方法,允许请求通过返回True,不允许请求通过返回Falsedef allow_request(self, request, view):raise NotImplementedError('.allow_request() must be overridden')# 获取IP地址def get_ident(self, request):# 获取请求头中真实IP地址xff = request.META.get('HTTP_X_FORWARDED_FOR')# 获取代理IP地址remote_addr = request.META.get('REMOTE_ADDR')# 获取设置的允许的最大代理数,默认不设置为Nonenum_proxies = api_settings.NUM_PROXIES# 如果num_proxies不是None,说明设置了该值if num_proxies is not None:# 如果设置为0,或者 xff没有值if num_proxies == 0 or xff is None:# 返回代理IP地址return remote_addr#使用代理IP的话会有多个地址,使用逗号分割成一个listaddrs = xff.split(',')'''通过min函数,拿到允许的代理数和IP地址长度最小的值,使用-变成负数在addrs列表中通过该下标取对应值'''client_addr = addrs[-min(num_proxies, len(addrs))]return client_addr.strip()# 如果没有设置允许的代理数 并且xff有值则直接返回,否则返回remote_addrreturn ''.join(xff.split()) if xff else remote_addr# 等待时间,告诉客户端被限流,等待多久可以访问# 后续继承实现,可选def wait(self):return None
SimpleRateThrottle频率控制类,继承了BaseThrottle,添加和重写了一些方法,重点是添加了get_cache_key 方法,但必须自己实现该方法
推荐阅读
- 微服务组件--限流框架Spring Cloud Hystrix分析
- 快手点赞限流什么意思
- 中国移动再出招 移动无限流量卡多少钱一个月
- 综艺无限流是什么意思 无限流是什么意思
- 被限流了手机怎么处理
- 直播限流怎么解决
- 抖音怎么知道自己被限流了 怎么知道自己被限流了
- 小红书被限流多久恢复
- led车灯三根线怎么接
- 电信宽带套餐价格表2022 电信有没有无限流量套餐