神秘密室
95.62M · 2026-02-24
接口防刷是生产项目落地必须解决的问题,这篇文章会从架构的角度,分层次的讲讲如何解决这个问题。
接口防刷(Rate Limiting / Anti-scraping)的核心在于“识别请求”和“限制频率”
在client层我们并不能阻止真正的攻击者,属于“防君子不防小人”,主要目的是增加作弊成本,而不是彻底阻断。
下面是在这一层常见的措施。
UI 交互限制
图形/行为验证码 (CAPTCHA)
参数签名 (Signature) & 防重放
在这一层我们一定要挡住绝大部分的异常流量,保护后端服务不被压垮。
2.Nginx 反向代理层
IP 限流 (limit_req_zone) :这是最基础的。
# 定义限流空间,以 IP 为 key,限制每秒 10 个请求
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
server {
location /api/ {
# 应用限流,burst=5 允许瞬间突发 5 个,nodelay 立即处理
limit_req zone=api_limit burst=5 nodelay;
}
}
黑名单机制:Nginx 可以直接 deny 某些恶意 IP 段。
技术栈:Spring Cloud Gateway/Zuul,Kong, APISIX, Tyk,Higress。
策略:
这里就是业务层来阻断的地方了,可以针对某个业务进行更加精细的限流操作。
场景:限制某个用户 (User_ID) 在特定时间窗口内只能调用 N 次。
为什么用 Lua? 保证 Redis 操作(读+写)的原子性。
滑动窗口算法:比固定窗口更平滑,防止“临界点突发”问题。
ZSET。Key 是 User_ID:Action,Score 是时间戳。每次请求移除窗口外的数据,统计窗口内的数量。Java 生态:
Go 生态:
golang.org/x/time/rate:官方标准库,基于令牌桶。Request-ID,后端在拦截器和Redis中检查该 ID 是否已处理过。如果面对脚本,我们在这一层一般有什么解决方法呢?
动态风控/黑名单
人机验证升级
最后的兜底,防止数据错乱。
数据库唯一索引 (Unique Index)
coupon_record 表对 user_id + campaign_id 建唯一索引。悲观锁/乐观锁
UPDATE account SET balance = balance - 100, version = version + 1 WHERE id = 1 AND version = old_version。防止并发扣减刷成负数。ok,这就是接口防刷(限流)的分层操作,如果有错误或者笔误、或者有更好的建议,期待在评论区提出来,谢谢!