OpenTelemetry 分布式系统上下文传播
介绍
在分布式系统中,一个用户请求可能需要经过多个服务的处理。例如,电商系统中的下单操作可能涉及订单服务、库存服务和支付服务。上下文传播(Context Propagation) 是确保这些跨服务调用能够关联到同一个逻辑请求(如一次用户下单)的关键机制。OpenTelemetry 通过标准化协议(如 W3C TraceContext)实现了跨语言、跨框架的上下文传递。
核心概念
- 上下文(Context):包含当前请求的追踪信息(如TraceID、SpanID)和自定义键值对。
- 传播(Propagation):将上下文通过HTTP头、消息队列等媒介在服务间传递。
上下文传播的工作原理
1. 传播格式
OpenTelemetry 支持以下标准传播格式:
- W3C TraceContext(默认):通过
traceparent
和tracestate
HTTP头传递。 - B3:Zipkin使用的格式。
- Jaeger:通过
uber-trace-id
头传 递。
2. 代码示例(Node.js)
以下示例展示如何在两个服务间手动传播上下文:
服务A(发送请求):
const { trace, context, propagation } = require('@opentelemetry/api');
const axios = require('axios');
async function callServiceB() {
// 获取当前上下文
const activeContext = trace.setSpan(context.active(), tracer.startSpan('serviceA-operation'));
// 注入上下文到HTTP头
const headers = {};
propagation.inject(activeContext, headers, {
set: (carrier, key, value) => carrier[key] = value,
});
// 发送请求
const response = await axios.get('http://service-b/api', { headers });
console.log(response.data);
}
服务B(接收请求):
const { context, propagation } = require('@opentelemetry/api');
app.get('/api', (req, res) => {
// 从HTTP头提取上下文
const extractedContext = propagation.extract(context.active(), req.headers, {
get: (carrier, key) => carrier[key],
});
// 使用提取的上下文创建Span
const span = tracer.startSpan('serviceB-operation', {}, extractedContext);
// ...处理逻辑
span.end();
res.send('Done');
});