系统监控 (Monitoring)

OpenTracing 分布式链路追踪 (vertx-opentracing)

Deprecated

Vert.x 依托 Jaeger 客户端提供了对 OpenTracing 规范的集成。

你可以直接通过标准环境变量配置 Jaeger 客户端,并让 Vert.x 自动加载:

Vertx vertx = Vertx.vertx(new VertxOptions()
  .setTracingOptions(
    new OpenTracingOptions()
  )
);

你也可以传入自定义配置的 Tracer 实例以获得更精准的运行时掌控:

Vertx vertx = Vertx
  .builder()
  .withTracer(o -> new OpenTracingTracer(false, tracer))
  .build();

链路追踪策略 (Tracing Policy)

追踪策略定义了组件在启用追踪时的行为模式:

  • PROPAGATE:若当前存在活跃 Trace 则在其下上报 Span,若不存在则不主动创建新 Trace。

  • ALWAYS:在活跃 Trace 下上报 Span;若不存在活跃 Trace 则强制创建新的活跃 Trace 根节点。

  • IGNORE:该组件完全不参与任何链路追踪。

追踪策略通常在具体组件的 Options 中进行声明。

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)

虽然没有开箱即用的自动协程桥接,但只需经过极简的封装即可优雅实现:

  1. 继承 CoroutineVerticle

  2. 将每个 Route Handler 转换为挂起协程

  3. 使用 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()
            }
        }
    }
}