如何通过Micrometer将Hazelcast Map统计指标发送至Datadog
Spring Boot Cache + Hazelcast:缓存命中/未命中指标发送到Datadog
问题背景
我使用Spring Boot Cache实现Hazelcast缓存,希望将缓存命中、未命中指标发送至Datadog。已开启Hazelcast的统计功能与JMX,但指标未正常上报到Datadog。当前缓存可正常工作,且其他服务指标能正常发送至Datadog。
我尝试过自定义EntryListener,但发现该监听器仅支持监听添加、更新、删除、驱逐、过期及清空事件,无法直接统计命中/未命中——添加事件或许可对应未命中,但更新事件无法区分是命中后的更新还是其他场景。不想采用定期同步Map指标的方案,寻求更优解。
当前配置文件
hazelcast.yaml
hazelcast: network: join: multicast: enabled: false tcp-ip: enabled: false # change these 2 lines and set kubernetes enabled to false for local debug # enabled: true # members: 127.0.0.1 kubernetes: enabled: true namespace: my-namespace service-name: my-service metrics: enabled: true jmx: enabled: true map: default: statistics-enabled: true time-to-live-seconds: 86400 eviction: max-size-policy: PER_NODE eviction-policy: LFU size: 200000
application.yaml
management: endpoint: health: probes: enabled: true metrics: export: statsd: enabled: true flavor: datadog port: 8125 host: ${HOST_IP}
解决方案
1. 修复Hazelcast与Micrometer的集成
Hazelcast本身会统计hazelcast.map.gets.hits和hazelcast.map.gets.misses指标,但需要确保这些指标被Spring Boot的Micrometer捕获:
- 确保引入
hazelcast-spring依赖(版本需与Spring Boot兼容,比如Spring Boot 3.x对应Hazelcast 5.x),该依赖会自动将Hazelcast的Map统计绑定到Micrometer的MeterRegistry。 - 确认
hazelcast.map.default.statistics-enabled: true已生效,该配置会开启默认Map的统计功能,所有基于此Map的缓存都会生成命中/未命中数据。
如果之前未生效,可能是依赖缺失或版本不匹配,检查项目的依赖管理配置。
2. 自定义Spring Cache拦截器(推荐方案)
如果原生集成仍有问题,或者需要更细粒度的指标控制,直接在Spring Cache抽象层实现拦截器,统计命中/未命中:
步骤1:实现带指标统计的CacheInterceptor
import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.cache.interceptor.CacheInterceptor; import org.springframework.cache.interceptor.CacheOperationInvocationContext; import org.springframework.cache.interceptor.CacheOperationInvoker; import org.springframework.stereotype.Component; @Component public class MetricsCacheInterceptor extends CacheInterceptor { private final Counter cacheHits; private final Counter cacheMisses; public MetricsCacheInterceptor(MeterRegistry meterRegistry) { this.cacheHits = Counter.builder("cache.gets.hits") .tag("cache.provider", "hazelcast") .register(meterRegistry); this.cacheMisses = Counter.builder("cache.gets.misses") .tag("cache.provider", "hazelcast") .register(meterRegistry); } @Override protected Object invoke(final CacheOperationInvoker invoker, CacheOperationInvocationContext<?> context, Cache.ValueWrapper result) { // 缓存命中:查询到缓存结果 if (result != null) { cacheHits.increment(); } else { // 缓存未命中:执行目标方法后会写入缓存 cacheMisses.increment(); } return super.invoke(invoker, context, result); } }
步骤2:替换默认拦截器
创建配置类,将自定义拦截器设置为Spring Cache的默认拦截器:
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.interceptor.CacheInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @Configuration @EnableCaching public class CacheConfig { @Bean @Primary public CacheInterceptor cacheInterceptor(MeterRegistry meterRegistry) { return new MetricsCacheInterceptor(meterRegistry); } }
这种方案直接基于Spring Cache的抽象层,无需依赖Hazelcast内部事件,指标会自动通过Micrometer发送至Datadog,还能灵活添加自定义标签(比如缓存名称、业务场景)。
3. 验证指标上报
- 通过Spring Boot Actuator的
/actuator/metrics端点,查询cache.gets.hits和cache.gets.misses是否存在数据。 - 直接在Datadog平台搜索对应指标名称,确认数据是否正常上报。
内容的提问来源于stack exchange,提问作者Lior Derei
相关产品推荐
相关产品推荐

