直接在Nginx中通过OpenResty的shared dict与log_by_lua_block实现HTTP状态码毫秒级内存统计,支持上游/原始状态码区分、内置/metrics接口暴露、定时落库及异常降级。

直接在 Nginx 中实现 HTTP 状态码的实时监控与统计,无需外部代理或日志解析,关键在于利用 ngx_http_lua_module(OpenResty)结合共享内存(shared dict)完成毫秒级聚合。
核心设计:状态码计数器驻留内存,零磁盘 IO
避免轮询 access.log 或调用外部服务,所有计数操作都在内存中完成:
- 定义一个 shared dict 区域(如
status_metrics),大小设为 10M 足够支撑百万级 QPS 的状态码键值存储 - 每个状态码(如
"200"、"404"、"502")作为 key,整型 value 自增,原子操作保障并发安全 - 使用
log_by_lua_block在请求生命周期末尾触发计数,确保无论是否发生 error_page 重定向,原始响应状态码都被捕获
精准采集:区分 upstream 与 origin 状态码
默认 $status 是 Nginx 返回给客户端的状态码,但运维更关注后端真实健康状况:
- 用
$upstream_status获取上游响应状态(支持多个 upstream 时可用$upstream_cache_status辅助判断缓存路径) - 对 proxy_pass 场景,可同时记录
$upstream_http_x_app_status(若后端透传业务自定义状态) - 在 log_by_lua_block 中做条件分支,例如:
if ngx.var.upstream_status == "502" then dict:incr("upstream_502", 1) end
高效暴露:内置 /status/metrics 接口按需输出
不依赖 Prometheus Exporter 进程,Nginx 自身提供轻量 HTTP 接口:
- 配置 location ~ ^/status/metrics$ { access_by_lua_block { ... } content_by_lua_block { ... } }
- content_by_lua_block 遍历 shared dict,按预设格式(如 JSON 或 OpenMetrics 文本)输出,支持 ?format=json 或 ?limit=10 参数控制
- 添加 access_by_lua_block 做基础 IP 白名单或 token 鉴权,防止指标泄露
长期聚合:定时刷入时间序列数据库(可选增强)
shared dict 适合秒级/分钟级热数据,持久化需异步落库:
- 用 timer.at() 创建每 60 秒触发的后台定时器,在 Lua 中批量读取 dict 并通过 cosocket 发送至 InfluxDB 或 Prometheus Pushgateway
- 发送后调用 dict:flush_all() 清空当前周期数据(注意:仅清空非永久 key;建议用带过期时间的 set,如 dict:set("200", 0, 60))
- 异常时自动降级:网络失败则本地文件追加(log_to_file),恢复后补发,避免数据丢失
不复杂但容易忽略:务必在 nginx.conf 的 http 块顶层初始化 shared dict,并确保 worker_processes ≥ 1 且 lua_shared_dict 在所有 worker 间共享。实际部署前用 wrk 压测验证 10K QPS 下计数精度与延迟波动。











