线上出问题时,怎么把一个请求在 nginx、Flask、下游服务里的日志串起来?一个请求 ID 就够了,但有几个地方容易出错:要不要信任客户端传来的 ID、下游调用有没有带上、线程里还能不能拿到。这篇用真实的服务把它们逐项验证(日志基础见第 181 篇)。
不带头:响应头 X-Request-ID = 4c8cc86cde27(服务端生成,12 位)
带头 client-abc-123:响应头 X-Request-ID = client-abc-123
A 的日志:
[A] rid=4c8cc86cde27 A: 收到 /order
[A] rid=4c8cc86cde27 A: B 返回 42
[A] rid=client-abc-123 A: 收到 /order
[A] rid=client-abc-123 A: B 返回 42
B 的日志(A 调用 B 时把 ID 放进了请求头):
[B] rid=4c8cc86cde27 B: 查库存
[B] rid=client-abc-123 B: 查库存
同一次请求在 A、B 两边的 ID 相同:第 2 次 A={'client-abc-123'},B=client-abc-123实验里 A 与 B 是两个 gunicorn 服务,A 用 urllib 调用 B。
A 的响应头 ID = c1810bab2017;B 日志里的 ID = ['83119ed6a8a9'](B 自己生成了新的,链路断了)
不校验:响应头里的 ID 长度 313(原样回显) 校验:响应头里的 ID 长度 12,值 0d741930f6ef(重新生成)
/boom → 500 {"error":"internal","request_id":"64084e1c7e89"}(响应头 X-Request-ID = 64084e1c7e89)
[A] rid=- A: 后台线程里的日志
[A] rid=857849ba73d5 A: 视图里的日志nginx 访问日志里的 ID:['d5d5616c108bc8a6cff78d3017dcf334'];Flask A 日志:['d5d5616c108bc8a6cff78d3017dcf334', 'd5d5616c108bc8a6cff78d3017dcf334'];B 日志:['d5d5616c108bc8a6cff78d3017dcf334'] nginx 响应头 X-Request-ID:['d5d5616c108bc8a6cff78d3017dcf334', 'd5d5616c108bc8a6cff78d3017dcf334'](与 Flask 加的头同名,客户端看到的数量见上)