服务网格 22:访问日志怎样区分代理失败和业务失败
同一个 503,可能出现在不同的层
客户端看见 503,并不能判断是 inventory 自己返回、代理连接不上库存实例,还是请求根本没有选到可用目标。第 03 篇讨论了 listener、route、cluster 和 endpoint;第 21 篇又加入认证、授权两个可能提前结束请求的位置。访问日志的任务,是把代理观察到的结束原因与应用实际做过的事情对齐,而不是只重复一列 HTTP 状态码。
Envoy 的响应标志、%RESPONSE_CODE_DETAILS%、%UPSTREAM_HOST% 和 %UPSTREAM_TRANSPORT_FAILURE_REASON% 能给出比状态码更细的线索,字段可用性及具体文字随代理版本、过滤器和配置而变。没有匹配 route、上游连接失败、上游主动断开,都需要分别查看代理实际记录;有 UPSTREAM_HOST 也不保证应用处理完请求。客户端侧代理、服务端侧代理、网关和应用还可能各自记录同一个逻辑请求,必须写清观察点。
用请求 ID 对齐三条路径
实验输入固定为 frontend → orders 调用链(orders 先调用 inventory,成功后再调用 external-stub) 的同一只读 SKU,每个场景生成独立 X-Request-ID。在隔离环境启用可检索的 Envoy 访问日志,将请求 ID、响应码、响应标志、详情、上游地址和代理身份一起记录;当前 Go 应用已有 request_id、role、status 日志,可据此判断哪些应用 handler 实际运行。保存代理最终生效的日志配置;“启用了 Telemetry 资源”并不等于采集端收到日志。
第一组正例走正常 quote:从客户端收到的响应回溯 frontend、orders、inventory 和 external-stub 的日志。第二组移除测试路径的 route,仅在明确被改动的代理核对无路由详情和下游响应;不要预设必定是 503,route 匹配失败与目标 cluster 无健康端点也不能合成同一种问题。第三组保持 route 和 endpoint 可见,但让测试 Service 指向没有监听者的上游端口,对照代理连接错误及库存应用是否收到请求。第四组让应用自身返回 503:可以使用现有 frontend 的“候选上游配置为空”分支,但它是应用级空地址配置,不是 Kubernetes 空 EndpointSlice。
| 场景 | 首要取证问题 | 实际标志、详情、应用记录 |
|---|---|---|
正常 quote |
哪些代理和应用见到同一请求 ID? | NOT_RUN:无 Kubernetes/Istio/Envoy |
| 无路由 | 哪个代理提前结束,是否确无上游处理? | NOT_RUN |
| 错误上游端口 | 当前 route/endpoint 是什么,失败在连接哪一段? | NOT_RUN |
| 应用返回 503 | 目标应用是否记录同一 ID 和主动返回的 503? | NOT_RUN |
这些并非“状态码到根因”的静态对照表。如果应用确实返回 503,上游响应标志和详情可能与代理本地生成的 503 不同;如果代理有重试,单个客户端请求又可能对应多个上游尝试。记录每次尝试及最终响应,不用应用的最后一行日志替代客户端结果,更不要把没有应用日志直接当作应用没有执行的充分证明:还要排查采集丢失。
练习与参考解答
- 两条客户端日志都是 503,其中一条
inventory有同一请求 ID 的 503 应用日志,另一条完全没有。可以确定第二条是无路由吗?参考解答:不能;还可能连接失败、日志未采集或请求被认证授权提前结束。先比对对应代理的 route、响应详情、上游地址及日志采集完整性。 - 看到
UPSTREAM_HOST,是否可以断言业务写入成功?参考解答:不能。它只帮助定位代理选择或尝试的上游;写入要核对应用处理记录和最终副作用账本。
官方资料与系列导航
- Istio Envoy Access Logs:默认格式及可配置日志入口。
- Envoy access logging:访问日志格式与字段。
- Envoy response code details:代理结束请求的细分原因,实测时以冻结版为准。
系列导航:21 认证成功为何仍会被拒绝 → 22 访问日志怎样区分代理失败和业务失败(本文)→ 23 网格指标怎样用于 SLO。
