Micrometer 系列【63】统一观测:基于 Spring Boot 的生产级演示案例 | 基于 OTLP 集成 Prometheus + Jaeger

文章目录

  • [1. 演示说明](#1. 演示说明)
    • [1.1 本篇要做什么](#1.1 本篇要做什么)
    • [1.2 为什么可以直接推送数据](#1.2 为什么可以直接推送数据)
    • [1.3 和上篇的主要区别](#1.3 和上篇的主要区别)
  • [2. 环境搭建](#2. 环境搭建)
    • [2.1 引入依赖](#2.1 引入依赖)
    • [2.2 应用配置](#2.2 应用配置)
      • [2.2.1 指标 OLTP 导出配置](#2.2.1 指标 OLTP 导出配置)
      • [2.2.2 链路 OLTP 导出配置](#2.2.2 链路 OLTP 导出配置)
    • [2.3 Docker Compose 部署 Prometheus + Jaeger](#2.3 Docker Compose 部署 Prometheus + Jaeger)
  • [3. 运行与验证](#3. 运行与验证)
    • [3.1 启动](#3.1 启动)
    • [3.2 触发业务](#3.2 触发业务)
    • [3.3 Jaeger 看 Trace](#3.3 Jaeger 看 Trace)
    • [3.4 Prometheus 看指标](#3.4 Prometheus 看指标)

1. 演示说明

1.1 本篇要做什么

上篇我们实现了「订单 → 支付」业务链路的三个观测点(order.createpayment.createcheckout.create),并让 Prometheus 直接抓取应用暴露的 /actuator/prometheus 指标。

但那只打通了 Metrics(指标) 一条信号。业务观测产生的 Traces(链路) 信息,比如一次 checkoutorderpayment 的父子嵌套关系、订单号、支付流水号等上下文还留在应用内部。

本篇在同一个 demo 上,把两条信号都收敛到 OTLP(OpenTelemetry Protocol) 协议上:

  • Metrics :应用通过 OTLP 导出器把指标直接推给Prometheus
  • Traces :应用通过 OTLP 导出器把链路直接推给 Jaeger 存储与展示。

这样,你在 Jaeger 里能看到 checkout.create 展开成 order.create → payment.create 的完整调用树;在 Prometheus 里能看到相同业务产生的指标;二者还能通过 exemplar 互相跳转。


1.2 为什么可以直接推送数据

过去想用 OTLP 把指标发给 Prometheus,中间必须架一个 OpenTelemetry Collector------因为 Prometheus 是"拉取式 "设计,自己不会主动收 OTLP

但现在不一样了,两端都原生支持 OTLP

  • Prometheus :从 2.47 起内置了 OTLP 接收器(OTLP receiver) ,可以在 /api/v1/otlp/v1/metrics 直接接收 POST 上来的 OTLP 指标。
  • Jaeger :从 1.35 起原生内置 OTLP 接收器(gRPC :4317HTTP :4318),应用可以把链路直接推给它。

于是拓扑可以简化为:

应用只做一件事:把指标和链路都按 OTLP 协议 POST 出去,一个出口两种目的地。

依赖一引、配置一写,每次 observe() 的观测就同时产生:

  1. Metrics :低基数标签 → Timer 指标 → OTLP 推给 Prometheus
  2. Traces :高基数属性 → OpenTelemetry SpanOTLP 推给 Jaeger,checkout.create 会展开成 order.create → payment.create 的父子调用树。

1.3 和上篇的主要区别

对比项 上篇:Prometheus 直抓 本篇:OTLP 直连两端
指标 Prometheus 主动拉 /actuator/prometheus 应用 OTLP 主动推 /api/v1/otlp/v1/metrics
链路 应用 OTLP 主动推 Jaeger
推/拉 拉(pull) 推(push)
中间件 无(两端原生收 OTLP)

2. 环境搭建

2.1 引入依赖

版本由 spring-boot-starter-parentBOM 统一管理:

xml 复制代码
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc</artifactId>
        </dependency>

        <!-- 指标:OTLP 协议推送 -->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-otlp</artifactId>
        </dependency>
        
        <!-- 链路:OpenTelemetry bridge + OTLP 导出(Boot 4 独立模块) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-micrometer-tracing-opentelemetry</artifactId>
        </dependency>
        <!-- OTel 桥接:把 Micrometer 转成 OpenTelemetry -->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-tracing-bridge-otel</artifactId>
        </dependency>
        <!-- OTel OTLP Exporter:Tracing 通过 OTLP 导出 -->
        <dependency>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-exporter-otlp</artifactId>
        </dependency>

spring-boot-micrometer-tracing-opentelemetryBoot 4 新增的独立模块 ,负责将 Micrometer Observation 变成 OpenTelemetry Span,并通过 OTLP 导出。

OTLP Metrics 相关三组依赖:

依赖 干什么
spring-boot-micrometer-tracing-opentelemetry Spring Boot 自动装配接线模块,绑定配置类、创建 OTel 链路导出相关 Bean
micrometer-tracing-bridge-otel 桥接层:将 Micrometer Observation 转换为 OpenTelemetry Span
opentelemetry-exporter-otlp OTLP 导出实现,负责把 Span 通过 HTTP/gRPC 发送至 OTel Collector

Metrics 指标两组依赖:

依赖 模式 说明
micrometer-registry-prometheus 拉(pull) 自包含:Boot 4 自动装配出 PrometheusMeterRegistry 并暴露 /actuator/prometheus,Prometheus 来抓。只要引入 actuator 即可,无需额外导出组件
micrometer-registry-otlp 推(push) 自包含发送器:Jar内置OtlpHttpMetricsSender,不需要像链路追踪额外引入 exporter jar;Micrometer 原生实现OTLP指标HTTP客户端,周期推送指标至OTel Collector

这里只走 OTLP 推送,就删掉 micrometer-registry-prometheus

2.2 应用配置

两个最容易写错的地方:

  • url / endpoint 必须是完整路径MicrometerOTLP url 是整体当完整地址用的(不会自动拼 /v1/metrics),所以指标那行要精确到 /api/v1/otlp/v1/metrics;链路要精确到 /v1/traces
  • 链路属性名是 Boot 4 新命名management.otlp.tracing.endpoint4.0 已标记废弃(error 级别,写了会启动报错),改用 management.opentelemetry.tracing.export.otlp.endpoint

另外:在 Micrometer 1.17 / Boot 4.1(你这个模块的版本)里,指标 OTLP 导出只支持 HTTP/Protobuf,不支持 gRPC 导出。

2.2.1 指标 OLTP 导出配置

src/main/resources/application.yaml 追加:

yml 复制代码
management:
  # ------ 指标:OTLP 直接推给 Prometheus 的原生 OTLP 接收器 ------
  otlp:
    metrics:
      export:
        url: http://localhost:9090/api/v1/otlp/v1/metrics
        step: 10s                    # 推送周期,演示调小;生产默认 1m

完整参考 YAML

yml 复制代码
management:
  otlp:
    metrics:
      export:
        # ===================== PushRegistryProperties 父类通用推送配置 =====================
        # 是否开启 OTLP Metrics 指标导出
        enabled: true
        # 指标聚合上报周期(步进窗口),聚合完成后批量推送到OTLP Collector
        step: 30s
        # OTLP 请求建立连接超时时间,跨机房/公网环境建议适度调大
        connect-timeout: 2s
        # OTLP 请求读取响应超时,Collector负载较高时容易触发超时
        read-timeout: 15s
        # 单次网络请求最多打包发送的指标条数,指标量大避免单包过大;太小会产生大量请求
        batch-size: 5000

        # ===================== OtlpMetricsProperties OTLP 专有配置 =====================
        # OTLP 服务地址
        # HTTP协议:http://host:4318/v1/metrics
        url: http://otel-collector:4318/v1/metrics

        # 传输压缩模式:NONE / GZIP,高指标量场景推荐开启gzip降低网络流量
        compression-mode: gzip

        # 聚合时序类型:CUMULATIVE(累积值,默认) / DELTA(增量值)
        # CUMULATIVE:上报持续累加数值,后端计算差值;兼容性最好,绝大多数存储支持
        # DELTA:上报周期内增量;注意很多OTLP后端不支持,随意修改会丢指标
        aggregation-temporality: cumulative

        # 指标导出时间单位,Micrometer内部计时为纳秒,导出时统一转换
        base-time-unit: milliseconds

        # 默认直方图类型:
        # EXPLICIT_BUCKET_HISTOGRAM 显式桶直方图(配合手动配置bucket边界,和Prometheus原生一致)
        # EXPONENTIAL_BUCKET_HISTOGRAM 指数直方图(自动生成桶,无需预设边界)
        histogram-flavor: explicit_bucket_histogram

        # 指数直方图精度参数,取值范围0~20,数值越大精度越高、生成桶数量越多
        max-scale: 20

        # 指数直方图最大桶数量,仅对 EXPONENTIAL_BUCKET_HISTOGRAM 生效
        max-bucket-count: 160

        # 是否额外为直方图发布max最大值Gauge指标,部分监控面板依赖该指标展示最大值
        publish-max-gauge-for-histograms: true

        # 自定义HTTP请求头,常用于鉴权、传递租户标识
        headers:
          X-Tenant: business-a

        # SSL配置,关联Spring Boot SSL Bundle统一证书管理
        ssl:
          bundle: otlp-ssl

        # ===================== Meter 维度:单指标粒度覆盖全局直方图配置 =====================
        # 优先级:单指标配置 > 全局配置 > Micrometer内置默认值
        meter:
          http.server.requests:
            histogram-flavor: exponential_bucket_histogram
            max-bucket-count: 140

2.2.2 链路 OLTP 导出配置

yaml 复制代码
management:
  # ------ 链路:OTLP 直接推给 Jaeger 的 OTLP HTTP 接收器 ------
  # Boot 4 起属性名从 management.otlp.tracing.* 迁移为 management.opentelemetry.tracing.export.otlp.*
  opentelemetry:
    tracing:
      export:
        otlp:
          endpoint: http://localhost:4318/v1/traces
          transport: http
  # ------ 采样 ------
  tracing:
    sampling:
      probability: 1.0   # 演示全采样;生产默认 0.1

完整参考 YAML

yml 复制代码
management:
  opentelemetry:
    tracing:
      export:
        otlp:
          # OTLP Collector 接入地址
          # HTTP transport: http://otel-collector:4318/v1/traces
          # GRPC transport: http://otel-collector:4317
          endpoint: http://otel-collector:4318/v1/traces

          # 完整调用总超时:DNS解析、TCP连接、发送span、服务端处理、接收响应全过程上限
          # 包含所有重试、重定向耗时,超时后本次批次span丢弃
          timeout: 10s

          # TCP连接建立超时时间
          connect-timeout: 10s

          # 传输协议:HTTP / GRPC
          # GRPC吞吐量更高,大规模链路推荐;HTTP便于抓包调试
          transport: HTTP

          # 传输负载压缩:GZIP / NONE
          # 链路量较大时开启GZIP降低网络流量消耗
          compression: GZIP

          # 自定义请求头,常用于鉴权、租户隔离
          headers:
            X-Tenant: business-a
            Authorization: Bearer ${OTEL_TOKEN:}

          # SSL配置,关联Spring Boot SSL Bundle,访问HTTPS类型OTLP端点时使用
          ssl:
            bundle: otlp-ssl

2.3 Docker Compose 部署 Prometheus + Jaeger

就两个服务:

yaml 复制代码
services:
  prometheus:
    image: prom/prometheus:latest
    container_name: ob-prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'
      - '--web.enable-lifecycle'
      - '--web.enable-otlp-receiver'
      - '--enable-feature=otlp-write-receiver'
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  jaeger:
    image: jaegertracing/all-in-one:latest
    container_name: ob-jaeger
    ports:
      - "16686:16686"   # Jaeger UI
      - "4318:4318"     # OTLP HTTP(应用推 traces 走这个)
      - "4317:4317"     # OTLP gRPC(预留)

指标是 进来的,Prometheus 不需要写任何 scrape 任务

prometheus.yml 可以增加服务全局属性:

yml 复制代码
otlp:
  promote_resource_attributes:
    - service.name
    - service.instance.id

3. 运行与验证

3.1 启动

bash 复制代码
# 1) 起 Prometheus + Jaeger
docker compose up -d

# 2) 起应用
cd micrometer-boot-demo
mvn spring-boot:run

启动后应用会异步向两个 OTLP 端点推送;Prometheus/Jaeger 没起时应用也能正常启动,只是日志出现连接报错。

3.2 触发业务

bash 复制代码
# 下单
curl -X POST "http://localhost:8080/api/order/create?orderNo=NO-001&userId=1001&orderType=NORMAL"

# 支付成功
curl -X POST "http://localhost:8080/api/order/pay?orderId=ORD-TEST001&payChannel=WECHAT"

# 支付失败(演示错误链路)
curl -X POST "http://localhost:8080/api/order/pay?orderId=ORD-TEST002&payChannel=FAIL"

# 结算:下单 + 支付 嵌套
curl -X POST "http://localhost:8080/api/checkout?orderNo=NO-002&userId=1002&orderType=VIP"

3.3 Jaeger 看 Trace

打开 http://localhost:16686Service spring-micrometer-serviceSearch 即可看到请求的链路。

最值得看的是 checkout 那条,三个观测自动形成父子调用树:

3.4 Prometheus 看指标

打开 http://localhost:9090 查看某个指标:

json 复制代码
order_create_seconds_count{instance="192.168.7.84:8080", job="spring-micrometer-service"}

几点说明:

  • OTLP 翻译后的具体指标名与 Prometheus 版本的 UTF-8 命名、翻译策略有关,以 UI 里实际看到的为准。
  • OTLP 接收器属于推模式 ,与拉模式的差异要注意:没有 up 指标(因为不是 scrape),也没有抓取超时/拉取侧告警,这些推模式语义需要另做监控。
  • 官方将其定位为实验性 能力,适合中小规模;高吞吐场景仍建议用 Collector 缓冲或保留 scrape

相关推荐
csdn2015_1 小时前
springboot +mybatis 查询myql开启程序级别缓存
spring boot·缓存·mybatis
chuan.bai1 小时前
Java RAG 实战(第 8 篇):Spring Boot RAG 查询 API
java·spring boot·贪心算法
猫吃了源码1 小时前
CentOS7使用Kubeadm安装部署K8s(Kubernetes)最新稳定版本1.26.x
云原生·容器·kubernetes
vx-程序开发2 小时前
springboot旅游推介平台---附源码24175
java·spring boot·python·spring cloud·eclipse·django·idea
小蒜学长2 小时前
“喵汪联盟”宠物领养系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·宠物
张忠琳2 小时前
【k3s】AutoK3s v0.9.3 —— Part 7 辅助模块超深度逐行分析
云原生·容器·kubernetes·k3s·autok3s
xbgRS5 小时前
springboot的自动装配
java·spring boot
张忠琳12 小时前
【k3s】AutoK3s v0.9.3 Part 1 入口与 CLI 命令模块 — 超深度逐行分析之三
云原生·容器·kubernetes·k3s·autok3s
嘻哈∠※12 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端