【问题标题】:Will updating a micrometer gauge ever block the calling thread?更新千分尺会阻塞调用线程吗?
【发布时间】:2021-08-18 19:43:23
【问题描述】:

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

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

谢谢 塔里克

【问题讨论】:

    标签: micrometer spring-micrometer


    【解决方案1】:

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

    如果您的意思是“发送”指标的线程,则该线程将被阻止。这通常是一个单独的线程(因为大多数注册表都是基于推送的),但在 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-30
      相关资源
      最近更新 更多