Будет ли обновление микрометрического датчика когда-либо блокировать вызывающий поток?

#micrometer #spring-micrometer

Вопрос:

Будет ли обновление микрометрического датчика когда-либо блокировать вызывающий поток (например, выполнять ввод-вывод)?

Я полагаю, что ответ «нет, ввод-вывод происходит в отдельном потоке сбора метрик», но хотел бы знать об исключениях из этого, крайних случаях ..

Спасибо, Тарик

Ответ №1:

Это зависит от того, что вы подразумеваете под вызовом потока. Если вы имеете в виду пользовательский поток, который регистрирует датчик, ответ будет отрицательным, в этот момент метод, который вы передаете датчику, даже не вызывается.

Если вы имеете в виду поток, который будет «отправлять» метрики, он будет заблокирован. Обычно это отдельный поток (поскольку большинство реестров основаны на выталкивании), но в случае Prometheus (который основан на вытягивании) датчик заблокирует конечную точку Prometheus и поток, который ее обслуживает.

По этой причине в микрометре вместо регистрации метода блокировки на датчике у вас может быть промежуточный объект «состояние», который вы периодически обновляете из отдельного потока (блокировка) и считываете его с датчика (неблокирующий), например:

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

И вы можете изменить currentValue из другого потока, см. Документы

Вы можете сделать это с любыми произвольными объектами, например:

 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;
    }
}