OpenResty通过log_by_lua_block精准捕获耗时并用shared dict实时聚合,毫秒级响应、高并发不丢数:一、按场景选准确耗时字段(upstream_response_time或ngx.now()差值);二、用lua_shared_dict内存聚合请求量、极值、分位样本;三、按接口路径+host等标签多维统计,暴露Prometheus指标及/metrics/api接口;四、在access_by_lua_block识别超时与错误,联动告警与限流。

OpenResty 可以在请求生命周期的关键阶段(尤其是 log_by_lua_block)精准捕获耗时数据,并结合共享字典或 Redis 实现实时统计与分析。它不是靠日志文件事后解析,而是边处理边聚合,毫秒级响应、高并发不丢数。
一、获取准确的接口耗时字段
原生 Nginx 的 $request_time 是从接收首字节到发送完响应的总时间,包含网络延迟;而真正反映后端处理效率的是 $upstream_response_time(反向代理场景)或 ngx.now() - ngx.req.start_time()(纯 Lua 处理逻辑)。推荐按场景选择:
- 若走 upstream(如转发给 Tomcat/Go 服务):直接用
ngx.var.upstream_response_time,注意它可能是 "-"(失败未返回)或带单位的字符串(如 "0.123"),需清洗转换 - 若全量 Lua 处理(如 content_by_lua_block 返回 JSON):在 handler 开头记录
local start = ngx.now(),结尾计算local cost = ngx.now() - start - 若需更细粒度(如 DB 耗时、缓存耗时):在对应 Lua 子过程前后打点,自行累加
二、用 shared dict 做内存级实时聚合
在 nginx.conf 的 http 块中定义共享字典,用于存储滑动窗口内的统计值:
然后在 log_by_lua_block 中更新:
- 提取路径(如
/api/user/profile)作为 key 维度 - 将耗时转为毫秒整数(如
math.floor(cost * 1000)) - 写入共享字典:用
dict:incr累计请求数、dict:hset更新最大值/最小值、dict:lpush(配合定时器清理)维护最近 100 条样本做分位计算 - 避免阻塞:所有操作必须是非阻塞的,不调用 sleep 或外部 I/O
三、按接口路径做多维统计与导出
统计不只是“平均值”,要支持运维快速定位问题:
- 区分路径粒度:对
/api/order/create和/api/order/list单独建模,不能混在一起算均值 - 打标关键上下文:把
ngx.var.host、ngx.var.http_user_agent(是否 App)、ngx.var.arg_v(版本号)等作为标签维度,便于下钻分析 - 暴露 Prometheus 指标:用
lua-resty-prometheus库注册直方图api_latency_seconds{path="/api/user", host="api.example.com"},桶区间建议设为 0.05s–2.0s(覆盖 99% 接口典型范围) - 提供 HTTP 接口查实时数据:在
location /metrics/api中读 shared dict 并返回 JSON,供看板或告警调用
四、补强:异常与长尾耗时专项捕获
平均值掩盖问题,要主动识别慢请求和错误模式:
- 在
access_by_lua_block中判断是否超时(如耗时 >1s),记录标记到共享字典,触发异步告警 - 对返回码非 2xx 的请求,在
log_by_lua_block中单独统计api_error_count{path=..., status="500"} - 用
lua-resty-limit-traffic配合耗时阈值,自动对单 IP 下的慢接口限流,防雪崩


















