一、OpenTracing简介
OpenTracing是一个由云原生计算基金会(CNCF)维护的跨语言的追踪标准。它提供了一套标准跟踪规范,使得跨多个组件、多个进程、多个主机的分布式系统的调用关系可视化。 通过OpenTracing可以将分布式系统中每一个操作的耗时、请求的参数、响应结果、错误信息等都进行精细化的记录和监控,从而可以更加快速、准确地定位和解决分布式系统中的问题。 OpenTracing的核心API非常简单,只提供了几个基本的追踪接口。除此之外,它可以支持许多各种语言和框架的插件,如Java、Go、Python、Ruby等。在使用上,OpenTracing通常需要搭配一些特定的Instrumentation或是框架 Support来使用。
二、OpenTracing API
OpenTracing定义了大量的接口方法,其中最基本的有以下几个:
- startSpan:创建一个Span对象实例
- inject:把当前Span实例写入到carrier对象中,如HTTP headers、RPC envelopes等
- extract:根据提供的carrier对象,重新生成一个Span实例
- setActiveSpan:在一个线程或请求上下文中设置活动的Span实例
- getActiveSpan:获取当前活动的Span实例
- close:结束某一个Span实例的追踪
以下是Java代码的样例:
// 定义一个追踪器
Tracer tracer = ...
// 假设tracer支持createChildTracer方法
Span childSpan = tracer.createChildTracer("child-operation")
.start();
try (Scope childScope = tracer.withSpan(childSpan)) {
// 业务逻辑
doSomeWork();
childSpan.setTag("message", "hello, world!");
childSpan.finish();
} catch (RuntimeException ex) {
childSpan.setTag("error", true);
childSpan.log(Collections.singletonMap("event", "error"));
throw ex;
}
上述代码中,以tracer.createChildTracer("child-operation").start()
的方式来创建一个子追踪器,Scope
则可以让Span的上下文在执行作用域内保持一致。业务逻辑执行完成后,通过childSpan.setTag("message", "hello, world!")
来为跟踪器添加自定义的标签。最后一定不要忘记调用childSpan.finish()
来关闭追踪。
三、OpenTracing实用案例
在分布式系统中,我们经常会遇到调用链过长、错误难以定位、请求性能低下等问题。使用OpenTracing可以越过进程、主机甚至数据中心的边界对系统进行完整性的分析和监控。 以下是一个将Spring with OpenTracing的集成例子:
@Bean
public Tracer tracer(Sampler sampler) {
TracingConfiguration tracingConfig = TracingConfiguration.builder()
.withSampler(sampler)
.withReporter(reporter)
.build();
return OpenTracingConfiguration.create(tracingConfig);
}
@Bean
public SpanAccessor getSpanAccessor(Tracer tracer) {
return new SpanAccessor(tracer);
}
@Controller
@RequestMapping("/greeting")
public class GreetingController {
private final GreetingService greetingService;
private final SpanAccessor spanAccessor;
public GreetingController(GreetingService greetingService, SpanAccessor spanAccessor) {
this.greetingService = greetingService;
this.spanAccessor = spanAccessor;
}
@GetMapping("/hello")
public ResponseEntity<String> hello(@RequestParam(value = "name") String name) {
Span greetingSpan = spanAccessor.getSpan();
greetingSpan.setBaggageItem("user", name);
greetingService.greet();
return ResponseEntity.ok("hello, " + name);
}
}
上述代码中,创建了一个tracer的Bean,然后定义了控制器GreetingController
,在hello
接口返回前通过SpanAccessor
获取span实例,并为其设置了baggage信息和在greeting
method中使用了Trace等AOP的注解以启动跟踪。
四、OpenTracing性能考量
OpenTracing在分布式追踪中有着很广泛的应用,也是商业化的APM工具常用的一个开源标准之一。但是由于实时的数据采集和传输不可避免,会对系统性能造成一定的影响,因此我们在使用时需要注意以下几点:
- 选择采样率:在不损失过多数据完整性的前提下,我们可以对数据进行截留或是丢弃。一般情况下需要根据业务负载、数据容量等来设置合适的采样率,避免数据压力过多。
- 数据发送优化:传统的同步的追踪方式会增加额外的I/O延迟,因此可以选择异步发送或者采用并行的数据传输技术来优化。同时,可以通过压缩数据、合并请求等方式来减少数据传输次数。
- 避免过度记录:OpenTracing记录的所有信息都会占用额外的资源,因此不应该记录过多的信息。在记录时应该优先选择关键的信息,如请求参数、响应结果、处理时间等。
五、总结
本文介绍了OpenTracing的定义和基本API,包括Span、Scope、Tracer等API的使用。同时,我们还介绍了OpenTracing在分布式追踪中的实用案例,以及在性能考虑时需要注意的地方。 通过OpenTracing,我们可以轻松地找到和追踪请求的调用链、性能瓶颈以及错误根源。最终可以提高关键业务应用的可靠性和性能,提升用户体验。