监控 lua 动态限流拦截率需由 lua 主动暴露拦截计数指标,通过 prometheus 抓取并计算比率:在 init_worker_by_lua_block 定义 counter,在拦截分支调用 inc(),确保与总请求数标签一致,再用 rate() 计算同窗口内比率。

要监控 Lua 模块实现的动态限流拦截率,关键不是靠 Prometheus 原生抓取“拦截动作”,而是由 Lua 主动暴露拦截计数指标,并通过 Prometheus 抓取、计算比率。Nginx 本身不自动上报 Lua 中的拦截行为,必须手动埋点。
在 Lua 脚本中定义并递增拦截计数器
使用 nginx-lua-prometheus 库,在 access_by_lua_block 或 rewrite_by_lua_block 中判断是否触发限流逻辑(如 Redis 查询超阈值、规则匹配 SQL 注入等),一旦执行 ngx.exit(403) 或跳过后续处理,就同步调用计数器递增:
- 定义拦截指标(放在
init_worker_by_lua_block):metric_blocked = prometheus:counter("nginx_lua_blocked_total", "Total requests blocked by Lua WAF/limiting", {"reason", "host"}) - 在拦截分支中记录:
if should_block then<br> metric_blocked:inc(1, {"rate_limit_exceeded", ngx.var.server_name})<br> ngx.exit(403)<br>end - 确保该计数器与请求总数(如
nginx_http_requests_total)使用相同标签维度(尤其是host),便于后续按域名聚合计算拦截率
配置 Prometheus 抓取 metrics 端点
确保 Nginx 已暴露 /metrics 接口(通过 content_by_lua_block { prometheus:collect() }),并在 Prometheus 的 scrape_configs 中正确配置 job:
- 目标地址为 Nginx 所在主机 + 指标端口(如
nginx-host:9145) - 若使用 OpenResty,默认可复用 80/443 端口下的
/metricslocation;建议单独开一个非业务端口(如 9145)避免暴露风险 - 确认 Prometheus 能成功抓取,且返回内容中包含
nginx_lua_blocked_total行
用 PromQL 计算拦截率
拦截率 = 拦截请求数 ÷ 总请求数(同时间窗口、同标签)。推荐用 rate() 计算每秒速率再做除法,更稳定:
- 全站 5 分钟拦截率:
rate(nginx_lua_blocked_total[5m]) / rate(nginx_http_requests_total[5m]) - 按域名查看 top 3 拦截率(Grafana 可视化常用):
topk(3, (rate(nginx_lua_blocked_total{host=~".+"}[5m]) / rate(nginx_http_requests_total{host=~".+"}[5m])) * 100)(结果单位为 %) - 注意:若某域名无拦截,分母为 0 会导致结果为
+Inf,可用or vector(0)处理,或 Grafana 中启用 “Null value → None”
补充:关联拦截原因提升可排查性
拦截计数器的 reason 标签是分析关键。建议在 Lua 中区分场景打标:
-
"ip_rate_exceeded"(IP 级频率超限) -
"redis_blocked"(Redis 黑名单命中) -
"sql_inject"(SQL 注入特征匹配) - 这样可在 Grafana 中用变量下拉选择 reason,快速定位哪类策略生效最多
不复杂但容易忽略的是:所有指标必须在同一个 scrape interval 内被采集,且标签完全对齐。否则 PromQL 除法会因 label mismatch 返回空结果。











