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