【发布时间】:2021-08-18 19:43:23
【问题描述】:
更新千分尺是否会阻塞调用线程(例如执行 I/O)?
我相信答案是“不,I/O 发生在单独的指标收集线程中”,但我想知道这方面的例外情况、边缘情况……
谢谢 塔里克
【问题讨论】:
标签: micrometer spring-micrometer
更新千分尺是否会阻塞调用线程(例如执行 I/O)?
我相信答案是“不,I/O 发生在单独的指标收集线程中”,但我想知道这方面的例外情况、边缘情况……
谢谢 塔里克
【问题讨论】:
标签: micrometer spring-micrometer
这取决于你调用线程是什么意思。 如果您的意思是注册仪表的用户线程,答案是否定的,此时您提供给仪表的方法甚至不会被调用。
如果您的意思是“发送”指标的线程,则该线程将被阻止。这通常是一个单独的线程(因为大多数注册表都是基于推送的),但在 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;
}
}
【讨论】: