首页 > 解决方案 > 计数器在千分尺中是线程安全的吗

问题描述

我正在尝试发布我的应用正在处理的事件数量。这是我在接收端的代码:

public void process(List<String> batch) {
    logger.info ("Processing batch of size " + batch.size())
    metrics.incrementCounter(MetricsType.CONSUMER_TOTAL_PROCESSED, batch.size)
}

类 Metrics 是:

public class Metrics {
    private static final Map<MetricsType, Counter> COUNTER_MAP = new ConcurrentHashMap<>();

    public Metrics(
        @Autowired MeterRegistry meterRegistry
    ) {
        COUNTER_MAP.put(
            MetricsType.CONSUMER_TOTAL_PROCESSED,
            Counter.builder("CONSUMER_TOTAL_PROCESSED").register(meterRegistry)
        );

        COUNTER_MAP.put(
            MetricsType.CONSUMER_DUPLICATE_PROCESSED,
            Counter.builder("CONSUMER_DUPLICATE_PROCESSED").register(meterRegistry)
        );
    }

    public void increment(MetricsType metricsType, int size) {
        COUNTER_MAP.get(metricsType).increment(size);
    }
}

枚举MetricsType包含所有类型的计数器。

process方法随时被 16 个线程调用。我面临的问题是打印计数的记录器,而在 grafana 中报告的总计数​​还有很长的路要走。

每次增加计数器时都必须同步吗?


编辑 - 我的意思是计数关闭是,如果有两个大小为 200 的日志,那么 grafana 应该报告总计数器 400。我通过花费 2 小时的时间范围来验证这一点,我从日志中提取所有大小并添加它们。


如果您偶然发现这一点并看到两个来源之间的差异,请检查您在 Grafana 中的最大数据点数是多少,这就是我认为计数器可能不是线程安全的实际问题。

标签: javaspringgrafanamicrometerspring-micrometer

解决方案


计数器是线程安全的,在内部它们使用一些原子数据结构进行计数。鉴于您的代码,我怀疑记录器打印的内容与您在 grafana 中看到的完全不同,因为记录器打印当前批次的大小,而计数器打印所有批次大小的总和。


推荐阅读