【问题标题】:Is io.prometheus.client.Gauge can be used for thread safety countersio.prometheus.client.Gauge 是否可用于线程安全计数器
【发布时间】:2020-09-21 06:52:57
【问题描述】:

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

    private Map<String, Gauge> gaugeMap = new ConcurrentHashMap<>();
    
    // 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);
        }
    }

以下是我的客户端代码。

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


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

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

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

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

【问题讨论】:

  • gaugeMap.put(metricName, gauge); computeIfAbsent,否则多个线程可能会在Map中放入相同的键
  • 是的,但情况并非如此,因为registerCounter 是从@PostConstruct 调用的,所以它只会在应用程序启动时被strat up 线程调用。一旦应用程序启动,就根本没有注册电话。

标签: java spring-boot prometheus spring-boot-actuator prometheus-java


【解决方案1】:

仪表是线程安全的,并使用 CAS 操作来支持非阻塞状态更新。所有的度量收集器都是。最后,它们必须由端点在单独的线程中公开。因此,读取和写入的状态应该是一致的。 要记住的一件事是,争用越高,CAS 操作的效率就越低。因此,请确保不要将它暴露给试图同时更新它的数十个线程。

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

【讨论】:

    【解决方案2】:

    Prometheus JVM Client README 声明:

    Gauge 上的默认 inc()dec()set() 方法负责线程安全

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      • 1970-01-01
      相关资源
      最近更新 更多