验证关联 ID 的传播
目标
手动创建 W3C traceparent 并将其传播到三级服务链中,再按跟踪 ID 关联日志,还原单个请求的路径。
为什么重要
如果仅用“因为它是第三种信号,所以有必要”来解释分布式跟踪,采用工作就会失败。必须知道它究竟能回答什么问题。假设十个服务的 p99 全都正常,但用户界面却需要 2 秒——在这种情况下,指标从原理上就无能为力。因为指标是聚合值,无法还原单个请求的路径。一个请求中执行 340 次耗时 4ms 的查询所造成的 N+1 问题,也绝不会出现在指标中,因为每次查询都很快。本实验不使用 SDK,只通过三个请求头片段来还原这条路径,让你今后接入 OpenTelemetry 时,能够在理解实际发生了什么的基础上进行接入。
步骤
- 使用
/opt/app/chain.py启动网关(8120)、订单(8121)、库存(8122)三个服务。GET http://127.0.0.1:8120/order返回 200。 - 使用
/root/trace/gen.py创建 traceparent,并将其作为一行保存到/root/trace/tp.txt。格式必须为00-<32hex>-<16hex>-01。 - 使用该请求头调用网关。三个服务分别在
/root/trace/svc-<이름>.log中留下trace_id=<값>,且三个值必须全部相同。 - 每份日志中还要留下
span_id=<16hex>和parent_span_id=<16hex>。三个服务的span_id必须各不相同。 - 使用
/root/trace/join.sh,只从三份日志中提取具有相同 trace_id 的行,并按时间顺序在/root/trace/joined.log中留下 3 行。 - 执行
/opt/app/brokenchain.sh后,会在 8123/8124/8125 上启动第二条服务链,其中一个服务会丢弃请求头。每个服务在/root/trace/broken-<이름>.log中留下svc=<이름> in_trace=<값> out_trace=<값>。找出传入跟踪 ID 与传出跟踪 ID 不同的服务,并将其名称作为一行写入/root/trace/broken.txt。 - 在
/root/trace/selftime.txt中写入slowest=<서비스명> total_ms=<정수>和self_ms=<정수>两行。self 是总时长减去子区段后的值。
参考
- traceparent 格式:
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01 - 跟踪 ID 在整个请求中保持相同,跨度 ID 则会在每一跳发生变化。
- 传播中断的四个位置:自有 HTTP 客户端、线程池传递、消息队列、删除请求头的代理。
- 常见错误:使用大写十六进制创建跟踪 ID——规范要求使用小写。
启动三级链式服务
使用 /opt/app/chain.py 启动网关(8120)、订单(8121)、库存(8122)三个服务。GET http://127.0.0.1:8120/order 返回 200。
/opt/app/chain.py 会在作为参数传入的端口上启动,并通过环境变量接收下一跳地址。请按网关、订单、库存的顺序启动三个服务。
创建 traceparent 请求头
使用 /root/trace/gen.py 创建 traceparent,并将其作为一行保存到 /root/trace/tp.txt。格式必须为 00-<32hex>-<16hex>-01。
用连字符连接 2 位版本、32 位跟踪 ID、16 位跨度 ID 和 2 位标志。全部必须是小写十六进制。
将同一个跟踪 ID 传递到链路末端
使用该请求头调用网关。三个服务分别在 /root/trace/svc-<이름>.log 中留下 trace_id=<값>,且三个值必须全部相同。
让每个服务从收到的请求头中原样传递跟踪 ID,并将其记录在自己的日志中。
每一跳都更改跨度 ID
每份日志中还要留下 span_id=<16hex> 和 parent_span_id=<16hex>。三个服务的 span_id 必须各不相同。
发送时,在父跨度 ID 的位置填入自己的跨度 ID。三份日志中的跨度 ID 全部不同时才是正常结果。
按跟踪 ID 关联三份日志
使用 /root/trace/join.sh,只从三份日志中提取具有相同 trace_id 的行,并按时间顺序在 /root/trace/joined.log 中留下 3 行。
按跟踪 ID 过滤各服务的日志文件,再按时间顺序拼接。关联结果必须恰好为 3 行。
找出传播中断的服务
执行 /opt/app/brokenchain.sh 后,会在 8123/8124/8125 上启动第二条服务链,其中一个服务会丢弃请求头。每个服务在 /root/trace/broken-<이름>.log 中留下 svc=<이름> in_trace=<값> out_trace=<값>。找出传入跟踪 ID 与传出跟踪 ID 不同的服务,并将其名称作为一行写入 /root/trace/broken.txt。
其中有一个服务会故意丢弃请求头。只需找到跟踪 ID 发生变化的位置。
计算自身耗时
在 /root/trace/selftime.txt 中写入 slowest=<서비스명> total_ms=<정수> 和 self_ms=<정수> 两行。self 是总时长减去子区段后的值。
从总持续时间中减去各个子跨度的时间。最慢的区段和自身耗时最长的位置可能不同。