更新千分尺是否会阻塞调用线程?

Will updating a micrometer gauge ever block the calling thread?

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

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

谢谢 塔里克

这取决于你所说的调用线程是什么意思。 如果你指的是注册仪表的用户线程,答案是否定的,此时你提供给仪表的方法甚至都没有被调用。

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

出于这个原因,在 Micrometer 中,您可以拥有一个中间“状态”对象,您可以从单独的线程(阻塞)定期更新并从仪表(非-阻塞),例如:

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

并且您可以从另一个线程修改 currentValue,请参阅 docs

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

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

其中 getValue 不阻塞只是给你最新的值,而在另一个线程上你可以更新封装在 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;
    }
}