Spring Boot集成Spring Cloud Sleuth与JMS:@JmsListener追踪问题
嘿,这个问题我之前帮朋友解决过,现在Spring Cloud Sleuth早就支持JMS的链路追踪了,你遇到的情况大概率是依赖版本或者配置的小问题,我给你一步步捋清楚怎么搞定:
解决Spring Cloud Sleuth对@JmsListener的追踪问题
1. 先确认依赖版本是否达标
早期的Sleuth版本(比如2016-2017年的版本)确实对JMS的支持不完善,但从**Spring Cloud Hoxton版本(对应Spring Boot 2.2+)**开始,Sleuth已经内置了对JMS的自动追踪支持。所以第一步要检查你的依赖版本:
- 如果你用Maven,确保
spring-cloud-starter-sleuth和spring-cloud-starter-zipkin(如果需要链路可视化)的版本和Spring Cloud版本匹配:
<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. 确保消息生产者传递追踪头
Sleuth会自动在JMS消息属性里注入X-B3-TraceId、X-B3-SpanId这些追踪标识,但前提是你用Spring的JmsTemplate发送消息——它会被Sleuth自动拦截并添加追踪头。如果是手动构造消息发送,就得手动把当前追踪上下文的信息塞进消息属性里:
@Autowired private Tracer tracer; @Autowired private JmsTemplate jmsTemplate; public void sendJmsMessage(String destination, String content) { Span currentSpan = tracer.currentSpan(); if (currentSpan != null) { jmsTemplate.send(destination, session -> { TextMessage textMessage = session.createTextMessage(content); // 注入B3追踪头 textMessage.setStringProperty("X-B3-TraceId", currentSpan.context().traceId()); textMessage.setStringProperty("X-B3-SpanId", currentSpan.context().spanId()); textMessage.setStringProperty("X-B3-Sampled", "1"); // 标记为需要采样 return textMessage; }); } else { // 没有追踪上下文时直接发送 jmsTemplate.convertAndSend(destination, content); } }
3. 开启Sleuth的JMS支持(默认已开启,保险起见检查下)
在新版本中,Sleuth默认已经启用了JMS追踪,但如果你的配置里不小心禁用了,可以在application.yml里明确开启:
spring: sleuth: jms: enabled: true
4. 自定义JMS监听器的追踪逻辑(可选)
如果默认的追踪信息不够用,比如想自定义span名称、添加业务标签,可以实现SpanAdjuster接口来扩展:
@Component public class CustomJmsSpanAdjuster implements SpanAdjuster { @Override public Span adjust(Span span, Message message) { // 把span名称改成更有业务意义的名字 return span.name("jms-listener-" + message.getJMSDestination()) .tag("message-type", message.getClass().getSimpleName()) .tag("destination", message.getJMSDestination().toString()); } }
5. 排查常见坑点
- 检查是否有其他JMS拦截器覆盖了Sleuth的拦截器,确保Sleuth的JMS拦截器优先级更高;
- 确认你的
@JmsListener所在的类是Spring管理的Bean,已经被容器扫描到; - 如果用的是ActiveMQ这类特定JMS实现,要确认没有禁用自定义消息属性的传递——有些MQ默认会过滤非标准属性。
内容的提问来源于stack exchange,提问作者Arpit
相关产品推荐
相关产品推荐

