
这篇指南帮助你用 Nginx(一种 Web 服务器)的 limit_req 模块为登录接口和 API(应用程序接口)配置速率限制,防止暴力破解和高频请求拖垮服务。限流不是把所有请求都卡住,而是让正常用户不受影响的同时,把异常高频请求挡在门外。
如果你已经做过 WordPress 安全加固,限流是其中的应用层防护补充。Hostease 中文博客的 数据库优化指南讲了查询层面的性能,本文则聚焦入口层面的流量控制:怎么配、怎么测、怎么避免误伤正常用户。
一、limit_req 的工作原理
limit_req 基于令牌桶算法。Nginx 为每个限流键(通常是客户端 IP)维护一个请求桶,按设定速率往桶里放令牌,请求来时如果桶里有令牌就放行,没有就排队或拒绝。两个核心参数决定限流行为:
- rate:令牌填充速率,如 10r/s 表示每秒放 10 个令牌。
- burst:突发队列长度,允许短时间超过速率的请求排队等待,而不是立即拒绝。
理解 burst 很关键:rate 设为 10r/s 但用户在 100ms 内发了 5 个请求,如果没有 burst,后 4 个会被拒绝。设 burst=5 后,这 5 个请求会排队按速率处理,不会立即拒绝但会延迟。如果排队也满了,才会返回 503。
二、为登录接口配置限流
登录接口是暴力破解的主要目标。以下配置限制每个 IP 每秒最多 1 次登录请求,突发最多 5 次排队。
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
}
server {
location /wp-login.php {
limit_req zone=login burst=5 nodelay;
proxy_pass http://backend;
}
}
nodelay 参数让 burst 内的请求立即处理而不是排队等待,适合登录场景:正常用户偶尔快速重试不会被延迟,但连续高频请求会被限流。10m 的共享内存区可以记录约 16 万个 IP,对于中小站点足够。

三、为 API 配置限流
API 限流需要更精细的策略。不同接口的合理速率不同:查询类可以宽松,写入类需要严格。可以用 location 分别配置。
limit_req_zone $binary_remote_addr zone=api_read:10m rate=20r/s;
limit_req_zone $binary_remote_addr zone=api_write:10m rate=5r/s;
location /api/v1/query {
limit_req zone=api_read burst=10 nodelay;
proxy_pass http://backend;
}
location /api/v1/update {
limit_req zone=api_write burst=3 nodelay;
proxy_pass http://backend;
}
查询接口设为 20r/s 允许较高并发,写入接口设为 5r/s 更保守。burst 分别设为 10 和 3,让正常批处理请求可以短时间突发。如果你的 API 后端连了数据库,写入限流还能间接保护数据库,避免高频写入拖慢查询,这点和 MySQL 慢查询治理配合效果更好。
四、避免误伤正常用户
限流最容易出问题是误伤。以下场景需要注意:NAT 出口 IP 共享时,多个用户的请求合并到一个 IP,单个 IP 速率限制会把正常用户也限住。解决方法是提高 rate 或用更精细的限流键(如 IP 加 URI、IP 加 API key)。移动端用户在弱网下会自动重试失败请求,如果限流把这些重试也拒绝了,用户体验会很差。建议移动端接口的 burst 设得比桌面端更宽松,容忍网络抖动导致的合理重试。
另一个常见误伤场景是搜索引擎爬虫。爬虫的高频抓取可能触发限流,导致页面不被索引。可以在限流规则前用 map 匹配爬虫 User-Agent 并放行,或者为爬虫单独配置更宽松的 rate。但要注意不要完全免除爬虫限流,恶意爬虫可以伪造 User-Agent 绕过防护。建议结合请求频率和访问模式综合判断,而不是只看 User-Agent 标识。
| 限流键 | 精度 | 适用场景 |
|---|---|---|
| $binary_remote_addr | IP 级 | 通用防护 |
| $binary_remote_addr$uri | IP + 路径 | 区分接口速率 |
| $http_x_api_key | API key 级 | 多租户 API |
CDN(内容分发网络)场景下,所有请求的来源 IP 都是 CDN 节点 IP,直接用 IP 限流会把 CDN 节点的所有用户合并限流。此时需要用 $http_x_real_ip 或 $http_x_forwarded_for 提取真实客户端 IP 作为限流键。如果你做过 多层缓存架构配置,CDN 回源时的限流键设置需要和缓存层的真实 IP 传递一致。
五、测试与验证

配置后必须测试验证。用 ab(Apache Benchmark)或 wrk 模拟高并发请求,确认限流按预期工作。
ab -n 100 -c 20 https://example.com/wp-login.php wrk -t4 -c20 -d10s https://example.com/api/v1/query
观察 Nginx 错误日志中的 limiting requests 信息,确认超限请求被记录和拒绝。正常用户的请求不应出现在限流日志中。如果正常用户也被限流,说明 rate 或 burst 太低,需要调整。测试时建议先设宽松参数,逐步收紧到目标值,观察业务是否正常。
除了即时测试,长期监控也很重要。限流配置上线后应该在日志分析平台统计每日被限流的请求数量和涉及的 IP。如果某个 IP 被频繁限流但业务没有异常报告,可能是该 IP 后面的用户有合理的高频需求(如批量操作或轮询),需要在限流策略中为这类场景留出余量或用白名单放行。同时要监控 503 错误率,如果限流导致 503 错误明显增加,说明参数过于严格。限流参数不是一次配好就不用改的,业务流量增长后需要定期复核和调整。
如果你的服务在 容器安全加固后的环境中运行,Nginx 限流仍然适用,因为限流发生在反向代理层,不受容器网络策略影响。但要注意容器化部署时 Nginx 的共享内存区(limit_req_zone 的 zone 大小)在多实例部署下是各自独立的,每个 Nginx 实例各自计数,总限流效果会是单实例 rate 乘以实例数。如果需要全局限流,应该用统一的 API 网关或 Redis(一种内存数据库)做分布式限流,而不是依赖单实例 Nginx。
总结
Nginx limit_req 限流配置的核心是选对 rate 和 burst:rate 控制平均速率,burst 容忍合理突发。登录接口用低 rate 高 burst 防暴力破解,API 用分接口策略平衡读写。限流键的选择决定误伤范围,NAT 和 CDN 场景需要用真实 IP 而非连接 IP。对于 Hostease 环境上的 Web 服务,限流是应用层防护的第一道闸门,和数据库优化、安全加固配合使用效果最好。