django-ratelimit不够用因其依赖视图装饰器、对类视图支持弱,无法多维度限流,不支持滑动窗口,且默认内存缓存上线易失效;推荐drf原生throttling方案配合redis缓存。
为什么 django 自带的 django-ratelimit 不够用?
因为 django-ratelimit 依赖视图装饰器,对类视图(尤其是 apiview 或 viewset)支持弱,且无法细粒度控制「按用户/ip/令牌」多维度限流;它默认用内存缓存,上线后容易失效,也不支持滑动窗口算法。
实际项目中更推荐组合使用 djangorestframework-throttling(DRF 原生方案) + 自定义缓存策略:
- 它直接集成在 DRF 的
throttle_classes中,兼容APIView、ViewSet和路由级配置 - 支持
UserRateThrottle、AnonRateThrottle、ScopedRateThrottle三类基础策略 - 所有限流键(key)生成逻辑可重写,比如从 JWT token 提取 user_id 而非依赖 request.user
如何让同一个 API 对登录用户和游客用不同速率?
DRF 的限流类默认按请求来源自动分流:未认证请求走 AnonRateThrottle,已认证走 UserRateThrottle。但要注意它们共用同一个缓存前缀,容易冲突。
正确做法是显式分离缓存命名空间:
from rest_framework.throttling import UserRateThrottle, AnonRateThrottle <p>class BurstAnonThrottle(AnonRateThrottle): scope = 'anon_burst' rate = '5/min'</p><p>class SustainedUserThrottle(UserRateThrottle): scope = 'user_sustained' rate = '100/h' </p>
然后在视图中指定:
class MyAPIView(APIView):
throttle_classes = [BurstAnonThrottle, SustainedUserThrottle]
关键点:
-
scope必须唯一,DRF 会用它拼出缓存 key,如'throttle_anon_burst_192.168.1.1' - 不要只写
rate = '5/min'就完事——必须配scope,否则所有限流共享同一组计数器 - 如果用了 Redis 缓存,确认
CACHES配置里defaultbackend 支持原子 incr/decr 操作
怎么按 API 功能模块(比如支付、短信)单独限流?
用 ScopedRateThrottle,它根据视图的 throttle_scope 属性查对应速率,适合功能隔离场景。
例如短信发送接口需要独立限频,且允许高权限用户豁免:
class SMSRateThrottle(ScopedRateThrottle):
def allow_request(self, request, view):
if request.user.is_staff:
return True
return super().allow_request(request, view)
<h1>视图中</h1><p>class SendSMSView(APIView):
throttle_classes = [SMSRateThrottle]
throttle_scope = 'sms' # 对应 settings.py 中的 THROTTLE_RATES['sms']
</p>
并在 settings.py 中声明速率:
THROTTLE_RATES = {
'sms': '10/h',
'payment': '5/min',
}
注意:
-
throttle_scope值必须和THROTTLE_RATES字典 key 完全一致,大小写敏感 -
ScopedRateThrottle的 key 是scope + ident(ident 默认为 IP),若想按用户限流,需重写get_cache_key() - 别在中间件里全局加
ScopedRateThrottle,它只对设置了throttle_scope的视图生效
Redis 缓存没配好会导致限流完全失效吗?
会。DRF 限流默认用 cache['default'],如果这个 cache backend 是 LocMemCache(Django 默认开发模式),多个 gunicorn worker 进程之间无法共享计数器,结果就是“限流形同虚设”。
生产环境必须切到 Redis:
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
还要检查:
- 确认
django-redis已安装并加入INSTALLED_APPS - 限流 key 过期时间由
rate字符串隐含决定(如'100/h'→ TTL ≈ 3600 秒),不需要手动 setex - 用
redis-cli查看 key 是否真实写入:keys "throttle_*",观察计数是否递增
最常被忽略的是:限流中间件顺序。确保 'django.middleware.security.SecurityMiddleware' 在 'django.contrib.sessions.middleware.SessionMiddleware' 之后,否则匿名用户识别可能出错。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











