
本文详细阐述了在opentelemetry java中,如何通过上下文传播机制实现跨服务或跨线程的span关联,而非直接通过span id获取span对象。我们将深入探讨发送方如何注入(inject)当前上下文,以及接收方如何提取(extract)该上下文来正确创建子span,从而构建完整的分布式追踪链。
在分布式系统中,追踪请求的完整路径至关重要。OpenTelemetry通过Span来表示操作单元,并使用父子关系将它们连接成Trace。当一个请求跨越服务边界、线程边界甚至进程边界时,如何确保后续操作的Span能够正确地关联到其“父”Span,是实现完整追踪链的关键。开发者可能会直观地认为可以通过一个Span ID来“获取”对应的Span对象,但OpenTelemetry的设计理念并非如此。相反,它依赖于一种更为强大和灵活的机制——上下文传播(Context Propagation)。
上下文传播是OpenTelemetry中用于在不同组件、服务或进程之间传递追踪和Baggage信息的机制。它确保了分布式追踪中的因果关系得以正确维护。当一个操作启动另一个远程操作时(例如,通过HTTP请求调用另一个微服务),父Span的上下文信息需要被传递给子服务,以便子服务能够创建出正确关联的子Span。
这个上下文通常包含:
OpenTelemetry通过Context对象来封装这些信息,并提供TextMapPropagator接口来定义如何将Context序列化(注入)到特定的载体(如HTTP头)中,以及如何从载体中反序列化(提取)出Context。
立即学习“Java免费学习笔记(深入)”;
在OpenTelemetry Java中,实现跨服务Span关联主要涉及两个步骤:发送方注入上下文和接收方提取上下文。
当服务A调用服务B时,服务A需要将当前操作的追踪上下文注入到发送给服务B的请求中。这通常通过TextMapPropagator完成,它将Context对象的内容写入到HTTP请求头、消息队列头或其他自定义载体中。
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope; // 导入 Scope
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.api.OpenTelemetry;
import java.util.HashMap;
import java.util.Map;
public class SenderService {
private final Tracer tracer;
private final TextMapPropagator propagator;
public SenderService(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer("my-sender-service");
// 获取全局的TextMapPropagator,通常是W3CTraceContextPropagator
this.propagator = openTelemetry.getPropagators().getTextMapPropagator();
}
public Map<String, String> makeRemoteCall(String data) {
Span parentSpan = tracer.spanBuilder("sendDataToRemote").startSpan();
Map<String, String> headers = new HashMap<>();
try (Scope scope = parentSpan.makeCurrent()) { // 使用 Scope
// 将当前Span的上下文注入到HTTP请求头中
propagator.inject(Context.current(), headers, (carrier, key, value) -> {
carrier.put(key, value);
});
System.out.println("Injected headers: " + headers);
// 模拟进行远程调用,将headers随请求发送
// 例如:httpClient.post("http://remote-service/api", data, headers);
} finally {
parentSpan.end();
}
return headers; // 返回注入的头信息,供演示
}
}在上述代码中,propagator.inject()方法将当前活跃的Context(其中包含parentSpan的追踪信息)写入到headers这个Map中。这些headers随后会作为HTTP请求头的一部分发送给远程服务。
当远程服务B接收到请求时,它需要从请求头中提取追踪上下文,并用它来作为新创建Span的父上下文。
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope; // 导入 Scope
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.api.OpenTelemetry;
import java.util.Map;
public class ReceiverService {
private final Tracer tracer;
private final TextMapPropagator propagator;
public ReceiverService(OpenTelemetry openTelemetry) {
this.tracer = openTelemetry.getTracer("my-receiver-service以上就是OpenTelemetry Java 中跨服务 Span 关联与上下文传播实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号