You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为基于Spring Boot的Thrift微服务集成Zipkin链路追踪?

嘿,你的思路方向是对的——确实需要拦截承载Thrift的HTTP请求,在出入站链路中注入Zipkin的追踪上下文,从而打通整个调用链路。下面我给你梳理一套可落地的实现方案,基于Spring Cloud Sleuth(负责链路追踪上下文管理)和Zipkin(负责链路数据存储与展示)来做:

1. 先引入必要依赖

不管是Thrift服务端还是客户端的Spring Boot应用,都需要引入Spring Cloud Sleuth和Zipkin的依赖。如果用Maven的话,在pom.xml里加这些:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

如果是Gradle,就加:

implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-starter-zipkin'
2. 服务端:拦截Thrift HTTP请求,生成追踪Span

因为你的Thrift是通过HTTP传输的,请求类型是x-thrift,所以可以用Spring的HandlerInterceptor来拦截这类请求,创建并管理Zipkin的Span:

首先写一个拦截器类:

import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class ThriftHttpTraceInterceptor implements HandlerInterceptor {

    private final Tracer tracer;

    public ThriftHttpTraceInterceptor(Tracer tracer) {
        this.tracer = tracer;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 只拦截x-thrift类型的请求
        if ("x-thrift".equals(request.getHeader("Content-Type"))) {
            // 从请求头中提取B3追踪信息(如果客户端已经传递),没有的话创建新的Span
            Span span = tracer.nextSpan().name("thrift-http-server-handle");
            // 将Span设置到当前上下文
            try (Tracer.SpanInScope ws = tracer.withSpan(span.start())) {
                // 可以把TraceId放到MDC,方便日志关联
                request.setAttribute("zipkin-trace-id", span.context().traceId());
            }
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 结束Span
        if ("x-thrift".equals(request.getHeader("Content-Type"))) {
            Span currentSpan = tracer.currentSpan();
            if (currentSpan != null) {
                currentSpan.end();
            }
        }
    }
}

然后注册这个拦截器到Spring MVC的配置里:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final ThriftHttpTraceInterceptor thriftTraceInterceptor;

    public WebMvcConfig(ThriftHttpTraceInterceptor thriftTraceInterceptor) {
        this.thriftTraceInterceptor = thriftTraceInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(thriftTraceInterceptor)
                // 这里配置你的Thrift API的请求路径,比如"/thrift/**"
                .addPathPatterns("/thrift/**");
    }
}
3. 客户端:传递追踪上下文到Thrift服务端

客户端在发送Thrift HTTP请求时,需要把当前的Zipkin追踪信息(B3协议的头:X-B3-TraceId、X-B3-SpanId、X-B3-Sampled等)放到请求头里,这样服务端就能接续同一个链路。

如果你的客户端是用RestTemplate来发送HTTP请求的,可以给RestTemplate添加一个客户端拦截器:

import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.IOException;

public class ThriftClientTraceInterceptor implements ClientHttpRequestInterceptor {

    private final Tracer tracer;

    public ThriftClientTraceInterceptor(Tracer tracer) {
        this.tracer = tracer;
    }

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        // 只处理Thrift请求
        if ("x-thrift".equals(request.getHeaders().getFirst("Content-Type"))) {
            Span currentSpan = tracer.currentSpan();
            if (currentSpan != null) {
                // 添加B3协议的追踪头
                HttpHeaders headers = request.getHeaders();
                headers.add("X-B3-TraceId", currentSpan.context().traceId());
                headers.add("X-B3-SpanId", currentSpan.context().spanId());
                headers.add("X-B3-Sampled", currentSpan.context().sampled() ? "1" : "0");
            }
        }
        return execution.execute(request, body);
    }
}

然后把这个拦截器注册到RestTemplate:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import java.util.Collections;

@Configuration
public class RestTemplateConfig {

    private final Tracer tracer;

    public RestTemplateConfig(Tracer tracer) {
        this.tracer = tracer;
    }

    @Bean
    public RestTemplate thriftRestTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setInterceptors(Collections.singletonList(new ThriftClientTraceInterceptor(tracer)));
        return restTemplate;
    }
}

如果你的客户端是自定义的Thrift HTTP客户端,逻辑也是一样的:在构建HTTP请求时,从Tracer中获取当前Span的上下文,把B3头添加到请求里就行。

4. 配置Zipkin地址和采样率

在服务端和客户端的application.yml(或application.properties)里添加Zipkin的基础配置:

spring:
  zipkin:
    base-url: http://localhost:9411/  # 你的Zipkin服务地址
  sleuth:
    sampler:
      probability: 1.0  # 采样率,开发环境设为1.0,生产环境可以调整
5. 验证链路追踪
  1. 启动Zipkin服务(可以用Docker快速启动:docker run -d -p 9411:9411 openzipkin/zipkin)
  2. 启动Thrift服务端和客户端应用
  3. 调用客户端的接口,让它发起Thrift HTTP请求到服务端
  4. 访问http://localhost:9411,在Zipkin UI里就能看到完整的调用链路,包含客户端和服务端的Span信息

另外有个小提示:如果你的Thrift服务端是用Thrift官方的Servlet来处理请求的(不是Spring MVC的Controller),那可能需要用Filter来代替HandlerInterceptor,拦截逻辑和上面差不多,只是换成Filter的doFilter方法而已。

内容的提问来源于stack exchange,提问作者Manuel Jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:28:44