nginx中limit_req误限健康探针的解决方法是:在http块用map指令将/health、/livez等路径映射为空key,使请求绕过限流;再配置limit_req_zone与limit_req burst=20 nodelay应用到location。

在 Nginx 中使用 limit_req 时,健康检查探针(如 Kubernetes 的 liveness/readiness 请求、Consul 或 Prometheus 的 HTTP 检查)容易被误限流,导致服务被错误标记为不健康。解决方法是通过 map 指令识别探针请求,并将其映射为特殊标识,在 limit_req 中用 burst 和 nodelay 配合或直接跳过限制。
用 map 匹配探针路径并设为白名单变量
在 http 块中定义一个变量(例如 $limit_key),对常见健康检查路径(如 /health、/livez、/readyz、/ping)返回空值或固定值,使其不参与限流:
map $request_uri $limit_key {
default $binary_remote_addr;
~^/(health|healthy|livez|readyz|ping|probe|-/healthz) "";
}
注意:"" 表示空字符串,而 limit_req zone=xxx key=... 中若 key 为空,该请求将**完全绕过限流**(Nginx 文档明确说明:空 key 不触发限制)。
定义 limit_req zone 并应用到 location
先声明共享内存 zone(例如每秒最多 10 个请求,突发容量 20):
limit_req_zone $limit_key zone=api:10m rate=10r/s;
然后在对应 server 或 location 中启用,注意加 nodelay 避免排队延迟影响探针响应时间:
location / {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend;
}
更精细控制:区分探针与真实流量(可选)
如果希望探针完全不限,但其他请求仍严格限流,上面的 map 方案已足够。若还需记录探针访问或做额外处理,可补充:
- 用
log_by_lua_block(需 lua-nginx-module)或access_log的自定义日志格式标记探针 - 在
map中为探针设特定 key(如"probe"),再单独配置一个宽松 zone:limit_req_zone $probe_key zone=probe:1m rate=100r/s;,并在 location 内用if分流(但注意if在 location 中有局限,推荐优先用map+ 空 key) - 检查探针是否带特定 header(如
X-Real-IP: 10.0.0.0/8或User-Agent: kube-probe),可在map中联合匹配:map "$request_uri:$http_user_agent" $limit_key { ... }
验证与调试技巧
开启 Nginx 错误日志的 debug 级别(临时)可查看限流决策过程:
error_log /var/log/nginx/error.log debug;
测试时用 curl 模拟探针并观察响应头:curl -I http://your.site/health,确认无 503 Service Temporarily Unavailable;再用 ab 或 wrk 对普通接口压测,验证限流生效。
不复杂但容易忽略的是:确保 map 块在 http 级且位于 limit_req_zone 之前,变量名不要和内置变量冲突,路径正则以 ^/ 开头避免误匹配。











