文章目录
- 1. 演示说明
- 1.1 本篇要做什么
- 1.2 为什么可以直接推送数据
- 1.3 和上篇的主要区别
- 2. 环境搭建
- 2.1 引入依赖
- 2.2 应用配置
- 2.2.1 指标 OLTP 导出配置
- 2.2.2 链路 OLTP 导出配置
- 2.3 Docker Compose 部署 Prometheus + Jaeger
- 3. 运行与验证
- 3.1 启动
- 3.2 触发业务
- 3.3 Jaeger 看 Trace
- 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统一管理:
<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追加:
management:# —— 指标:OTLP 直接推给 Prometheus 的原生 OTLP 接收器 ——otlp:metrics:export:url:http://localhost:9090/api/v1/otlp/v1/metricsstep:10s# 推送周期,演示调小;生产默认 1m完整参考YAML:
management:otlp:metrics:export:# ===================== PushRegistryProperties 父类通用推送配置 =====================# 是否开启 OTLP Metrics 指标导出enabled:true# 指标聚合上报周期(步进窗口),聚合完成后批量推送到OTLP Collectorstep:30s# OTLP 请求建立连接超时时间,跨机房/公网环境建议适度调大connect-timeout:2s# OTLP 请求读取响应超时,Collector负载较高时容易触发超时read-timeout:15s# 单次网络请求最多打包发送的指标条数,指标量大避免单包过大;太小会产生大量请求batch-size:5000# ===================== OtlpMetricsProperties OTLP 专有配置 =====================# OTLP 服务地址# HTTP协议:http://host:4318/v1/metricsurl: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_histogrammax-bucket-count:1402.2.2 链路 OLTP 导出配置
management:# —— 链路:OTLP 直接推给 Jaeger 的 OTLP HTTP 接收器 ——# Boot 4 起属性名从 management.otlp.tracing.* 迁移为 management.opentelemetry.tracing.export.otlp.*opentelemetry:tracing:export:otlp:endpoint:http://localhost:4318/v1/tracestransport:http# —— 采样 ——tracing:sampling:probability:1.0# 演示全采样;生产默认 0.1完整参考YAML:
management:opentelemetry:tracing:export:otlp:# OTLP Collector 接入地址# HTTP transport: http://otel-collector:4318/v1/traces# GRPC transport: http://otel-collector:4317endpoint: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-aAuthorization:Bearer ${OTEL_TOKEN:}# SSL配置,关联Spring Boot SSL Bundle,访问HTTPS类型OTLP端点时使用ssl:bundle:otlp-ssl2.3 Docker Compose 部署 Prometheus + Jaeger
就两个服务:
services:prometheus:image:prom/prometheus:latestcontainer_name:ob-prometheuscommand:-'--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.ymljaeger:image:jaegertracing/all-in-one:latestcontainer_name:ob-jaegerports:-"16686:16686"# Jaeger UI-"4318:4318"# OTLP HTTP(应用推 traces 走这个)-"4317:4317"# OTLP gRPC(预留)指标是推进来的,
Prometheus不需要写任何scrape任务
prometheus.yml可以增加服务全局属性:
otlp:promote_resource_attributes:-service.name-service.instance.id3. 运行与验证
3.1 启动
# 1) 起 Prometheus + Jaegerdockercompose up-d# 2) 起应用cdmicrometer-boot-demo mvn spring-boot:run启动后应用会异步向两个OTLP端点推送;Prometheus/Jaeger没起时应用也能正常启动,只是日志出现连接报错。
3.2 触发业务
# 下单curl-XPOST"http://localhost:8080/api/order/create?orderNo=NO-001&userId=1001&orderType=NORMAL"# 支付成功curl-XPOST"http://localhost:8080/api/order/pay?orderId=ORD-TEST001&payChannel=WECHAT"# 支付失败(演示错误链路)curl-XPOST"http://localhost:8080/api/order/pay?orderId=ORD-TEST002&payChannel=FAIL"# 结算:下单 + 支付 嵌套curl-XPOST"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查看某个指标:
order_create_seconds_count{instance="192.168.7.84:8080",job="spring-micrometer-service"}几点说明:
OTLP翻译后的具体指标名与Prometheus版本的UTF-8命名、翻译策略有关,以UI里实际看到的为准。OTLP接收器属于推模式,与拉模式的差异要注意:没有up指标(因为不是scrape),也没有抓取超时/拉取侧告警,这些推模式语义需要另做监控。- 官方将其定位为实验性能力,适合中小规模;高吞吐场景仍建议用
Collector缓冲或保留scrape。