部署运维与容错韧性

暴露 Prometheus 监控指标并在 Grafana 中可视化

本文档将向你展示如何使用 Vert.x Micrometer Metrics 收集并暴露 Prometheus 监控指标,并在 Grafana 仪表盘中实现可视化实时监控。

你将构建什么

你将构建一个包含多个 REST 接口与定时任务的 Vert.x 应用程序,它能够:

  • 自动收集 Vert.x 核心事件循环(Event Loop)延迟、Event Bus 吞吐与 HTTP 请求指标;

  • 在 /metrics 端点暴露标准 Prometheus 格式指标;

  • 配合 Docker Compose 一键拉起 Prometheus 与预置 Grafana 仪表盘进行实时观测。

dashboard

前置要求

  • 文本编辑器或 IDE

  • Java 11 或更高版本

  • Maven

  • Docker 与 Docker Compose

创建工程项目

这是工程所需的 pom.xml 文件配置:

核心依赖为 vertx-micrometer-metrics 与 micrometer-registry-prometheus。

应用程序实现

在主入口中启用 Micrometer 监控指标并配置 Prometheus 注册表:

package io.vertx.howtos.metrics;

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
import io.micrometer.prometheusmetrics.PrometheusConfig;
import io.micrometer.prometheusmetrics.PrometheusMeterRegistry;
import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.eventbus.Message;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.web.Router;
import io.vertx.micrometer.MicrometerMetricsFactory;
import io.vertx.micrometer.MicrometerMetricsOptions;
import io.vertx.micrometer.PrometheusScrapingHandler;
import io.vertx.micrometer.VertxPrometheusOptions;

import java.util.concurrent.ThreadLocalRandom;

public class MainVerticle extends VerticleBase {

  // tag::greetings[]
  private static final String[] GREETINGS = {
    "Hello world!",
    "Bonjour monde!",
    "Hallo Welt!",
    "Hola Mundo!"
  };
  // end::greetings[]

  @Override
  public Future<?> start() {
    // tag::consumer[]
    Future<Void> registration = vertx.eventBus().consumer("greetings", msg -> {
      // Simulate processing time between 20ms and 100ms
      long delay = ThreadLocalRandom.current().nextLong(80) + 20L;
      vertx.setTimer(delay, l -> {
        // Choose greeting
        String greeting = GREETINGS[ThreadLocalRandom.current().nextInt(GREETINGS.length)];
        msg.reply(greeting);
      });
    }).completion();
    // end::consumer[]

    // tag::router[]
    Router router = Router.router(vertx);
    // end::router[]
    // tag::handler[]
    router.get("/greeting").handler(rc -> {
      vertx.eventBus().<String>request("greetings", null)
        .map(Message::body)
        .onSuccess(greeting -> rc.response().putHeader("content-type", "text/plain").end(greeting))
        .onFailure(throwable -> {
          throwable.printStackTrace();
          rc.fail(500);
        });
    });
    // end::handler[]
    // tag::scraping[]
    router.route("/metrics").handler(PrometheusScrapingHandler.create());
    // end::scraping[]

    // tag::http[]
    Future<HttpServer> httpServer = vertx.createHttpServer()
      .requestHandler(router)
      .listen(8080);
    // end::http[]

    return Future.join(registration, httpServer);
  }

  // tag::main[]
  public static void main(String[] args) {
    /*
     We can configure the metrics registry to enable histogram buckets
     for percentile approximations.
     */
    PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
    registry.config().meterFilter(
      new MeterFilter() {
        @Override
        public DistributionStatisticConfig configure(Meter.Id id, DistributionStatisticConfig config) {
          return DistributionStatisticConfig.builder()
            .percentilesHistogram(true)
            .build()
            .merge(config);
        }
      });

    Vertx vertx = Vertx.builder()
      .with(new VertxOptions().setMetricsOptions(new MicrometerMetricsOptions()
        .setEnabled(true)
        .setPrometheusOptions(new VertxPrometheusOptions()
          .setEnabled(true))
      ))
      .withMetrics(new MicrometerMetricsFactory(registry))
      .build();

    vertx.deployVerticle(new MainVerticle()).await();
    System.out.println("Verticle started");
  }
  // end::main[]
}
1 启用 Vert.x 监控指标系统
2 启用 Prometheus 指标桥接
3 挂载 /metrics 路由暴露 Prometheus 抓取端点

启动 Prometheus 与 Grafana

启动应用程序:

./mvnw clean compile exec:java

在另一个终端使用 Docker 启动监控基础设施:

docker run -d --name prometheus -p 9090:9090 -v $(pwd)/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
docker run -d --name grafana -p 3000:3000 grafana/grafana

导入我们预先准备的仪表盘模板文件 grafana/dashboard.json,你将立即看到关于 HTTP QPS、响应延迟分布、JVM 堆内存与事件循环调度的精美监控图表!

总结

本文档展示了:

  • 在 Vert.x 应用中开启 Micrometer 响应式指标监控;

  • 规范化暴露标准 Prometheus 抓取端点;

  • 在 Grafana 仪表盘中全方位透视 Vert.x 底层性能指标。