文章目录
- [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.create、payment.create、checkout.create),并让 Prometheus 直接抓取应用暴露的 /actuator/prometheus 指标。
但那只打通了 Metrics(指标) 一条信号。业务观测产生的 Traces(链路) 信息,比如一次 checkout 里 order 和 payment 的父子嵌套关系、订单号、支付流水号等上下文还留在应用内部。
本篇在同一个 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:4317、HTTP:4318),应用可以把链路直接推给它。
于是拓扑可以简化为:

应用只做一件事:把指标和链路都按 OTLP 协议 POST 出去,一个出口两种目的地。
依赖一引、配置一写,每次 observe() 的观测就同时产生:
- Metrics :低基数标签 →
Timer指标 →OTLP推给Prometheus。 - Traces :高基数属性 →
OpenTelemetry Span→OTLP推给 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-parent 的 BOM 统一管理:
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-opentelemetry 是 Boot 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必须是完整路径 :Micrometer的OTLPurl是整体当完整地址用的(不会自动拼/v1/metrics),所以指标那行要精确到/api/v1/otlp/v1/metrics;链路要精确到/v1/traces。- 链路属性名是 Boot 4 新命名 :
management.otlp.tracing.endpoint在4.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:16686,Service 选 spring-micrometer-service,Search 即可看到请求的链路。
最值得看的是 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。