← 中文资源

简体中文版本

添加限流中间件

为 Express 服务添加固定窗口限流,返回带 Retry-After 的 429,并理解内存限流何时不再正确。

阅读英文原文

限流是政策,不是数字

先选维度:按 IP、API key、用户还是租户。按 IP 简单,但会惩罚共享 NAT 后的用户;按 key 需要认证和密钥轮换。对昂贵或未认证路由施加更严格限制,并让健康检查不进入限流器。

内存实现只是起点

基于 Map 的限流器在单进程内正确。多实例位于负载均衡器后时,每个实例各自计数,客户端可能获得 N 倍预期限额。服务水平扩展时,应把计数器移到 Redis 或在网关执行限流。

清理很重要。按 IP 建键的 Map 在扫描流量下会无限增长。定期清扫过期桶,限制 map 大小,并考虑有界 LRU。攻击下会泄漏内存的限流器是新的漏洞。

返回有用的响应

返回 429,而不是 500。包含 Retry-After 和简短响应体。不要泄露内部配额或其他客户端信息。按采样率记录限流键和路由,隐私规则要求最小化时不要无限期记录原始 IP。

app.use(rateLimit({ windowMs: 60_000, max: 60 }));

验证边界

预期结果:窗口内恰好 60 个请求成功,第 61 个返回 429 且 Retry-After 为正数。用突发命令确认,并检查计数器按客户端地址而非代理地址建键。限流从不触发,或对所有客户端同时触发,说明键或 trust-proxy 配置有误。