SpringBoot 3集成测试中Zipkin追踪信息无法收集问题求助
问题分析与解决方案
1. 容器网络访问错误
你的Spring Boot测试进程和Zipkin容器不在同一个网络上下文里,配置中用localhost指向的是测试进程所在的主机/进程,而非Zipkin容器。即便给Zipkin容器加了网络别名zipkin,但配置未正确使用这个别名,导致应用无法将追踪数据发送到Zipkin服务。
修复方法:
修改@DynamicPropertySource,用容器网络别名zipkin替代localhost,直接访问容器内部的9411端口(无需用主机映射端口):
@DynamicPropertySource static void zipkinProperties(DynamicPropertyRegistry registry) { registry.add("spring.zipkin.baseUrl", () -> "http://zipkin:9411"); registry.add("management.zipkin.tracing.endpoint", () -> "http://zipkin:9411/api/v2/spans"); }
因为两者处于Testcontainers的共享网络中,通过别名即可直接通信,不用绕主机映射端口。
2. 依赖版本兼容问题
你手动指定了Micrometer和Zipkin Reporter的版本,可能和Spring Boot 3.1.3的依赖管理不兼容,导致追踪链路无法正常工作。
修复方法:
移除pom.xml中手动指定的版本号,让Spring Boot自动管理兼容版本:
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-brave</artifactId> <!-- 移除手动版本号 --> </dependency> <dependency> <groupId>io.zipkin.reporter2</groupId> <artifactId>zipkin-reporter-brave</artifactId> <!-- 移除手动版本号 --> </dependency>
3. 异步上报的时序问题
Zipkin的追踪数据是异步上报的,你在发送请求后立即查询Zipkin,此时数据可能还未完成上报。现有代码的sleep放在断言之后,完全起不到等待作用。
修复方法:
调整等待逻辑到查询Zipkin之前,且无需过长等待:
@Test void testRestEndpoint() { RestTemplate restTemplate = new RestTemplate(); // 发送测试请求 IntStream.rangeClosed(0,99).forEach(i ->{ restTemplate.getForObject("http://localhost:%s/status".formatted(port), String.class); }); String status = restTemplate.getForObject("http://localhost:%s/status".formatted(port), String.class); Assertions.assertEquals("OK", status); // 等待异步上报完成(10秒足够) sleep(10); // 再查询Zipkin验证数据 String zipkinResult = restTemplate.getForObject("http://localhost:%s/api/v2/spans?serviceName=spring-micrometer-tracing-demo".formatted(getPort()), String.class); Assertions.assertFalse("[]".equals(zipkinResult)); }
4. 容器启动等待条件优化
当前用/api/v2/spans?serviceName=anything作为启动完成的判断条件,但这个查询接口返回200不代表Zipkin已经准备好接收追踪数据。
修复方法:
改用Zipkin的健康检查端点作为等待条件:
static GenericContainer<?> zipkinContainer = new GenericContainer<>("openzipkin/zipkin:2.24-arm64") .withReuse(false) .withExposedPorts(9411) .waitingFor(Wait.forHttp("/health").forStatusCode(200).withStartupTimeout(Duration.of(2, ChronoUnit.MINUTES))) .withNetwork(Network.SHARED) .withNetworkAliases("zipkin");
健康端点返回200说明Zipkin服务已完全启动,可正常接收追踪数据。
内容的提问来源于stack exchange,提问作者Ozay Duman
相关产品推荐
相关产品推荐

