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

Apache Camel 2.x迁移至3.x/4.x后路由指标兼容性问题求助

兼容Apache Camel 3.x+的路由指标自定义标签实现方案

针对Camel 3.x及以上版本移除MicrometerRoutePolicyNamingStrategy.getTags(Exchange)方法后的自定义标签需求,以下是几个可行的实现方案:

方案一:自定义MicrometerMetricsService扩展指标标签

Camel 3.x+中,MicrometerRoutePolicy依赖MicrometerMetricsService处理指标逻辑,可通过自定义该服务的实现,在记录指标时注入Exchange相关标签:

  1. 实现自定义MicrometerMetricsService,重写recordExchangeEvent方法提取所需标签:
public class CustomMicrometerMetricsService extends DefaultMicrometerMetricsService {

    public CustomMicrometerMetricsService(MeterRegistry meterRegistry, MicrometerRoutePolicyNamingStrategy namingStrategy) {
        super(meterRegistry, namingStrategy);
    }

    @Override
    public void recordExchangeEvent(Exchange exchange, String eventType, long duration) {
        // 从Exchange中获取自定义属性
        String messageName = exchange.getProperty("messageName", String.class);
        // 构建自定义标签集合
        Tags customTags = Tags.of("messageName", messageName);
        
        // 调用父类方法时传入自定义标签
        super.recordExchangeEvent(exchange, eventType, duration, customTags);
    }
}
  1. 在Spring Boot配置中替换默认服务实例:
@Configuration
public class CamelMetricsConfig {

    @Bean
    public MicrometerMetricsService customMicrometerMetricsService(MeterRegistry meterRegistry, MicrometerRoutePolicyNamingStrategy namingStrategy) {
        return new CustomMicrometerMetricsService(meterRegistry, namingStrategy);
    }
}

方案二:通过EventNotifier手动上报自定义指标

利用Camel的事件监听机制,监听Exchange完成事件,手动向Micrometer上报带自定义标签的路由指标:

  1. 实现EventNotifier监听ExchangeCompletedEvent:
public class CustomExchangeMetricsNotifier extends EventNotifierSupport {

    private final MeterRegistry meterRegistry;

    public CustomExchangeMetricsNotifier(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Override
    public void notify(EventObject event) throws Exception {
        if (event instanceof ExchangeCompletedEvent) {
            ExchangeCompletedEvent completedEvent = (ExchangeCompletedEvent) event;
            Exchange exchange = completedEvent.getExchange();
            Route route = exchange.getUnitOfWork().getRouteContext().getRoute();
            
            // 提取自定义标签和指标数据
            String routeId = route.getId();
            String messageName = exchange.getProperty("messageName", String.class);
            long duration = exchange.getDuration();
            
            // 上报路由耗时指标
            Timer.builder("camel.route.exchange.duration")
                    .tags("routeId", routeId, "messageName", messageName)
                    .register(meterRegistry)
                    .record(duration, TimeUnit.MILLISECONDS);
            
            // 按需上报成功/失败计数
            if (exchange.isFailed()) {
                Counter.builder("camel.route.exchange.failed")
                        .tags("routeId", routeId, "messageName", messageName)
                        .register(meterRegistry)
                        .increment();
            } else {
                Counter.builder("camel.route.exchange.success")
                        .tags("routeId", routeId, "messageName", messageName)
                        .register(meterRegistry)
                        .increment();
            }
        }
    }

    @Override
    public boolean isEnabled(EventObject event) {
        return event instanceof ExchangeCompletedEvent;
    }
}
  1. 注册该EventNotifier到Camel上下文:
@Configuration
public class CamelEventConfig {

    @Bean
    public EventNotifier customExchangeMetricsNotifier(MeterRegistry meterRegistry) {
        return new CustomExchangeMetricsNotifier(meterRegistry);
    }
}

方案三:结合ThreadLocal与MeterFilter注入动态标签

通过ThreadLocal暂存Exchange的自定义属性,再利用Micrometer的MeterFilter全局添加标签:

  1. 创建ThreadLocal工具类暂存属性:
public class ExchangeTagContext {
    private static final ThreadLocal<String> MESSAGE_NAME = new ThreadLocal<>();

    public static void setMessageName(String messageName) {
        MESSAGE_NAME.set(messageName);
    }

    public static String getMessageName() {
        return MESSAGE_NAME.get();
    }

    public static void clear() {
        MESSAGE_NAME.remove();
    }
}
  1. 在路由中添加Processor存入并清理ThreadLocal:
from("direct:start")
        .process(exchange -> {
            String messageName = exchange.getProperty("messageName", String.class);
            ExchangeTagContext.setMessageName(messageName);
        })
        // 后续路由逻辑
        .to("mock:end")
        .process(exchange -> ExchangeTagContext.clear()); // 避免内存泄漏
  1. 自定义MeterFilter为Camel路由指标添加标签:
public class CamelRouteTagFilter implements MeterFilter {

    @Override
    public Meter.Id map(Meter.Id id) {
        // 仅对Camel路由相关指标添加标签
        if (id.getName().startsWith("camel.route.")) {
            String messageName = ExchangeTagContext.getMessageName();
            if (messageName != null) {
                return id.withTag("messageName", messageName);
            }
        }
        return id;
    }
}
  1. 注册MeterFilter到Spring Boot:
@Configuration
public class MicrometerConfig {

    @Bean
    public MeterFilter camelRouteTagFilter() {
        return new CamelRouteTagFilter();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:03:25