rest接口限流与防刷核心是在请求入口实时拦截、计数并决策,关键在于维度设计(ip/用户/接口)、算法选型(固定窗口/滑动窗口/令牌桶)和存储一致性(单机内存或redis)三方面取舍。

REST接口限流与防刷控制,核心是“在请求入口处做拦截+计数+决策”,不是靠事后监控,而是实时拒绝超限请求。关键不在于用什么技术,而在于维度设计(IP/用户/接口)、算法选型(固定窗口/滑动窗口/令牌桶)和存储一致性(单机内存 or 分布式Redis)这三个层面的取舍。
按维度选择限流策略
不同场景需匹配不同粒度:
- IP维度:适合防御脚本刷量、爬虫扫描。例如Nginx层用limit_req或Spring Boot中用HandlerInterceptor提取X-Forwarded-For后校验,配合CIDR白名单放行可信网段
- 用户维度:需登录态支撑,如Yii 2中让User模型实现RateLimitInterface,返回[100, 600]表示每个用户每10分钟最多100次;Django REST Framework用UserRateThrottle自动绑定当前user.id
- 接口维度:对高耗资源接口单独设限,比如导出接口限制为5次/小时,查询接口放宽至1000次/天。Spring Boot中可按request.getRequestURI()构造限流key
选对算法比堆代码更重要
固定窗口简单但有临界突变问题(如0:59和1:00各发100次就变成200次);生产环境推荐:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 滑动窗口:用Redis ZSet存时间戳+请求记录,ZREMRANGEBYSCORE清理过期项,再ZCARD统计当前窗口请求数——精度高、无突变
- 令牌桶:适合突发流量平滑,如API网关层用Guava RateLimiter预设每秒10个令牌,每次请求消耗1个,无令牌则阻塞或拒绝
- 漏桶:更强调匀速输出,适合后台任务类接口,Yii 2内置RateLimiter默认即基于漏桶逻辑(按timestamp和allowance递减)
必须处理的细节问题
很多项目上线后才发现这些坑:
- 真实IP识别要防伪造:不能只信request.getRemoteAddr(),需从X-Forwarded-For取第一个非内网地址,并校验前置代理是否可信
- 响应头要规范:返回429时带上X-Rate-Limit-Limit、X-Rate-Limit-Remaining、X-Rate-Limit-Reset,方便调用方做退避重试
- 排除路径要写全:Swagger、actuator、健康检查、静态资源等必须显式exclude,否则监控脚本自己把自己限流了
- 分布式下避免本地计数器失效:多实例部署时,内存AtomicInteger会各自计数,必须用Redis+Lua保证INCR和EXPIRE原子性
快速落地建议
小团队或MVP阶段优先走轻量方案:
- Spring Boot项目:用HandlerInterceptor + ConcurrentHashMap
+ ScheduledExecutorService定时清理过期key,先保单机可用 - Yii 2项目:直接扩展User模型,数据库加allowance和allowance_updated_at两字段,复用框架内置RateLimiter行为
- Django REST Framework:全局配置DEFAULT_THROTTLE_CLASSES和DEFAULT_THROTTLE_RATES,5分钟内改完生效
- 所有方案都要配429错误页或统一异常处理器,避免堆栈暴露内部结构










