You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Webflux中如何从异步值创建Micrometer Gauge指标?

从返回Mono的异步源创建Micrometer Gauge的实现方案

核心原理

Micrometer Gauge的取值逻辑是同步触发的(采集端拉取指标时会调用对应Supplier的get方法),本身不支持异步返回,直接在Supplier中调用Mono.block()会存在阻塞采集线程的风险,在Webflux环境下极易引发线程池耗尽等问题,因此推荐采用本地缓存最新值+异步更新缓存的方案实现。

方案1:原子变量缓存最新值(生产环境推荐)

这个方案是最稳妥的实现,Gauge直接读取本地原子变量的取值,异步源的结果定期/事件触发更新到原子变量中:

实现步骤

  1. 定义线程安全的原子变量存储最新的gauge取值
  2. 注册Gauge,绑定到原子变量的get方法
  3. 启动异步流订阅,将异步返回的结果更新到原子变量

代码示例

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicLong;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class AsyncGaugeConfig {
    // 存储gauge最新值的原子变量,支持并发安全的读写
    private final AtomicLong asyncGaugeValue = new AtomicLong(0);

    // 你的异步取值方法,替换为实际返回Mono的业务逻辑
    private Mono<Long> getAsyncValue() {
        return Mono.just(100L);
    }

    public AsyncGaugeConfig(MeterRegistry registry) {
        // 注册Gauge,直接从原子变量取值
        Gauge.builder("custom.async.gauge", asyncGaugeValue, AtomicLong::get)
                .description("异步源生成的gauge指标")
                .register(registry);

        // 启动定期更新逻辑,按需调整拉取间隔
        Flux.interval(Duration.ofSeconds(15))
                // 背压策略:如果更新速度慢于拉取速度,丢弃多余的拉取请求
                .onBackpressureDrop()
                .flatMap(ignore -> getAsyncValue()
                        // 异常处理:避免单次拉取失败导致整个流终止
                        .doOnError(e -> log.warn("异步gauge值拉取失败", e))
                        .onErrorResume(e -> Mono.empty()))
                // 更新原子变量的值
                .subscribe(asyncGaugeValue::set);
    }
}

适配说明

  • 如果异步值是事件驱动推送的,不需要定期拉取,直接订阅对应的事件流更新原子变量即可
  • 取值为double类型的话,把AtomicLong替换为AtomicDouble即可
  • IO密集型的异步取值逻辑,可以通过subscribeOn(Schedulers.boundedElastic())指定调度器适配

方案2:Supplier中直接阻塞取值(不推荐)

仅在指标采集频率极低、异步取值耗时极短的场景下可以临时使用,必须添加超时逻辑避免阻塞采集线程:

Gauge.builder("custom.async.gauge", () -> {
            // 一定要设置短超时,避免无限阻塞
            return getAsyncValue().block(Duration.ofMillis(200));
        })
        .register(registry);

风险说明

  • 采集端拉取指标时会同步阻塞等待Mono返回,超时会导致该指标采集失败
  • 大量这类Gauge会拖慢整个指标采集流程,甚至引发线程池耗尽

内容的提问来源于stack exchange,提问作者fyrkov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 14:33:01