Vertx vertx = Vertx.vertx(new VertxOptions()
.setTracingOptions(
new OpenTracingOptions()
)
);
OpenTracing 分布式链路追踪 (vertx-opentracing)
Vert.x 依托 Jaeger 客户端提供了对 OpenTracing 规范的集成。
你可以直接通过标准环境变量配置 Jaeger 客户端,并让 Vert.x 自动加载:
你也可以传入自定义配置的 Tracer 实例以获得更精准的运行时掌控:
Vertx vertx = Vertx
.builder()
.withTracer(o -> new OpenTracingTracer(false, tracer))
.build();
HTTP 服务端与客户端链路追踪
Vert.x HTTP 服务端与客户端会在处理 HTTP 请求前后自动上报 Span:
-
operationName:HTTP 请求方法 -
Tags 标签集:
-
http.method:HTTP 方法 -
http.url:请求 URL -
http.status_code:HTTP 状态码
-
HTTP 服务端默认追踪策略为 ALWAYS,可通过 setTracingPolicy 定制:
HttpServer server = vertx.createHttpServer(new HttpServerOptions()
.setTracingPolicy(TracingPolicy.IGNORE)
);
HTTP 客户端默认追踪策略为 PROPAGATE,可通过 setTracingPolicy 定制:
HttpClient client = vertx.createHttpClient(new HttpClientOptions()
.setTracingPolicy(TracingPolicy.IGNORE)
);
若需手动为客户端调用发起 Trace,首先创建 Span 并通过 OpenTracingUtil.setSpan 告知 Vert.x:
Span span = tracer.buildSpan("my-operation")
.withTag("some-key", "some-value")
.start();
OpenTracingUtil.setSpan(span);
// 执行具体操作,如发起客户端请求
span.finish();
在两个 Vert.x 微服务之间的 HTTP 调用中,客户端会自动创建 Span,随后将 Trace Context 传播给服务端并在服务端追加新的子 Span。
EventBus 事件总线链路追踪
Vert.x EventBus 在流转消息时会自动记录追踪 Span。
发送消息的默认策略为 PROPAGATE,可通过 setTracingPolicy 进行配置:
DeliveryOptions options = new DeliveryOptions().setTracingPolicy(TracingPolicy.ALWAYS);
vertx.eventBus().send("the-address", "foo", options);
获取当前活跃 Span
Vert.x 会将当前正在执行的 Span 实例安全保存在局部上下文(Local Context)中。
你可以通过 OpenTracingUtil.getSpan() 随时获取它。
该方法仅在 Vert.x 事件循环线程(VertxThread 实例)上生效;在非 Vert.x 外部线程上调用将直接返回 null。
Kotlin 协程支持 (Coroutines)
虽然没有开箱即用的自动协程桥接,但只需经过极简的封装即可优雅实现:
-
继承
CoroutineVerticle -
将每个 Route Handler 转换为挂起协程
-
使用 Kotlin 的
CoroutineContext传递并存储Tracer与当前Span对象
示例代码如下:
class TracedVerticle(private val tracer: Tracer): CoroutineVerticle() {
override suspend fun start() {
val router = Router.router(vertx)
router.get("/my-route").coroutineHandler { ctx ->
val span = tracer.buildSpan("my-route").start()
try {
// 在协程上下文中执行业务逻辑
ctx.response().end("Hello Traced World")
} finally {
span.finish()
}
}
}
}