io.prometheus.client.Gauge可以用于线程安全计数器吗

huangapple go评论93阅读模式
英文:

Is io.prometheus.client.Gauge can be used for thread safety counters

问题

我正在使用 io.prometheus.client.Gauge 来实现一个线程安全的计数器,以计算在一个时间范围内处理的事件数量。现在有几个线程正在处理这些事件。并且在完成处理时都可以更新计数器。我的问题是 Gauge 计数器在性质上是否是线程安全的?以下是我的实现。

private Map<String, Gauge> gaugeMap = new ConcurrentHashMap<>();

// 这个方法将被调用来注册计数器
private void registerCounter(String metricName) {
    Gauge gauge = Gauge.build()
            .name(metricName)
            .help(metricName)
            .register(meterRegistry.getPrometheusRegistry());
    gaugeMap.put(metricName, gauge);
}

public void incrementCounter(String metricName) {
    if (isCounterPresent(metricName)) {
        gaugeMap.get(metricName).inc();
    }
}

public void incrementCounter(String metricName, long value) {
    if (isCounterPresent(metricName)) {
        gaugeMap.get(metricName).inc(value);
    }
}

以下是我的客户端代码。

// 在应用启动时,我为所有指标调用 registerCounter
@PostConstruct
private void registerMetrics(List<String> metricList) {
    // 对于 metricList 中的每个指标,调用 registerCounter(String metricName)
}

Thread1
-------------------
// 处理 N 个事件
// 调用 incrementCounter("metric-1", N);

Thread2
-------------------
// 处理 N 个事件
// 调用 incrementCounter("metric-1", N);

Thread3
-------------------
// 处理 N 个事件
// 调用 incrementCounter("metric-1", N);

现在我的问题是,由于多个线程正在增加同一个计数器,那么它是否会给我正确的值?

英文:

I am using io.prometheus.client.Gauge to implement a thread safety counter to calculate the number of events processed in a time frame. Now there are several threads that are processing the events. And all can update the counter when it finishes the processing. My question ins is Gauge counters are thread safety in nature? Following is my implementation.

    private Map&lt;String, Gauge&gt; gaugeMap = new ConcurrentHashMap&lt;&gt;();
    
    // This method will be called to register the Gauge
    private void registerCounter(String metricName) {
    	Gauge gauge = Gauge.build()
    			.name(metricName)
    			.help(metricName)
    			.register(meterRegistry.getPrometheusRegistry());
    	gaugeMap.put(metricName, gauge);
    }
    
    public void incrementCounter(String metricName) {
    	if (isCounterPresent(metricName)) {
    		gaugeMap.get(metricName).inc();
    	}
    }
   public void incrementCounter(String metricName, long value) {
        if (isCounterPresent(metricName)) {
            gaugeMap.get(metricName).inc(value);
        }
    }

Following is my client code.

// on application startup I am calling registerCounter for all metrics
@PostConstruct
private void registerMetrics(List&lt;String&gt; metricList) {
	// for each of metricList --&gt; call registerCounter(String metricName)
}


Thread1
-------------------
// process N events
// call incrementCounter(&quot;metric-1&quot;, N);

Thread2
-------------------
// process N events
// call incrementCounter(&quot;metric-1&quot;, N);

Thread3
-------------------
// process N events
// call incrementCounter(&quot;metric-1&quot;, N);

Now my question is as multiple threads are incrementing the same counter, then will it give me the correct value?

答案1

得分: 3

计量器是线程安全的,并使用CAS操作支持非阻塞状态更新。所有的度量收集器也是如此。最终,它们必须由端点在线程中单独公开。因此,状态在读取和写入时应保持一致。
需要特别注意的一点是,争用越高,CAS操作的效率就越低。因此,请确保不要将其暴露给同时尝试更新它的数十个线程。

其次,将计量器用作计数器不是一个好主意,因为有一种专门的类型用于计数 - 计数器。一些Prometheus函数专门实现和优化,用于计数器 - 比如rate,irate等。因此,如果您需要收集和公开多个线程处理的事件数量,建议使用计数器。

英文:

The gauge is thread safe and uses CAS operation to support non-blocking state update. All the metric collectors are. In the end they has to be exposed by the endpoint in separate thread. Hence the state should be consistent for read and writes.
One particular thing to keep in mind is that the higher is contention the lower is efficiency of CAS operation. So make sure you don't expose it for tens of threads that are trying to update it at the same time.

Secondly, using gauge as counter is not a good idea as there is a special type for that - Counter. Some Prometheus functions are specifically implemented and optimized to be used for counters - rate, irate etc.
So in case you need to collect and expose the number of events processed by several threads the recommendation is to use Counter.

答案2

得分: 1

Prometheus JVM客户端README中指出:

> Gauge上的默认inc()dec()set()方法会处理线程安全性。

英文:

Prometheus JVM Client README states that:

> the default inc(), dec() and set() methods on Gauge take care of thread safety

huangapple
  • 本文由 发表于 2020年9月21日 14:52:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63987443.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定