首页 > 解决方案 > 更新千分尺会阻塞调用线程吗?

问题描述

更新千分尺是否会阻塞调用线程(例如执行 I/O)?

我相信答案是“不,I/O 发生在一个单独的指标收集线程中”但想知道这个例外情况,边缘情况,..

谢谢塔里克

标签: micrometerspring-micrometer

解决方案


这取决于调用线程是什么意思。如果您的意思是注册仪表的用户线程,答案是否定的,此时您提供给仪表的方法甚至不会被调用。

如果您的意思是“运送”指标的线程,那将被阻止。这通常是一个单独的线程(因为大多数注册表都是基于推送的),但在 Prometheus(基于拉取)的情况下,仪表将阻塞 Prometheus 端点和为其提供服务的线程。

出于这个原因,在千分尺中,您可以拥有一个中间“状态”对象,而不是向仪表注册阻塞方法,您可以从单独的线程定期更新(阻塞)并从仪表中读取它(非阻塞),例如:

AtomicInteger currentValue = registry.gauge("test.gauge", new AtomicInteger(0));

您可以currentValue从另一个线程修改,请参阅文档

您可以对任意对象执行此操作,例如:

State state = registry.gauge("test.gauge", Collections.emptyList(), new State(), State::getValue);

WheregetValue不阻塞只是给你最新的值,而在另一个线程上你可以更新封装在State对象中的值。

这里有几行表明您注册到仪表中的方法是阻塞的:

public class GaugeSample {
    public static void main(String[] args) throws InterruptedException {
        PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
        System.out.println("registering the gauge...");
        Gauge.builder("test.gauge", GaugeSample::getValue)
                .register(registry);

        System.out.println("scraping...");
        System.out.println(registry.scrape());
    }

    private static double getValue() {
        try {
            Thread.sleep(5_000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }

        return 42;
    }
}

推荐阅读