Micrometer 中的计数器线程安全吗

Are counters thread safe in Micrometer

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

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

class 指标是:

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 中的最大数据点数是多少,这就是我认为计数器可能不是线程安全的实际问题。

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

计数器单调递增。因此,如果前一批已经发生,那么新的一批将添加到前一批。

您使用的是什么后端?如果您使用的是 Prometheus,您可以将查询包装在一个 increase 函数中,这样您就可以看到计数器增加了多少。

(虽然要回答最初的问题:是的,计数器是线程安全的)