news 2026/9/26 5:39:31

Spring Boot可观测性实战:OTLP打通Jaeger、Prometheus、Loki

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot可观测性实战:OTLP打通Jaeger、Prometheus、Loki

在微服务架构里摸爬滚打几年的人,对“可观测性”这三个字应该都有点复杂的感情。指标、链路、日志,每一块单独拎出来都有成熟方案,但想把它们组合成一个整体,让一次请求从入口到数据库都能完整串起来,事情就变得棘手了。Spring Boot 4(以及当前主流的 3.x 版本)搭配 OpenTelemetry 的 OTLP 协议,把 Jaeger、Prometheus、Loki 串成一套完整的“指标 + 链路 + 日志”可观测性平台,是我最近在几个项目里落地得最顺畅的一条路径。这篇博文就围绕这条链路,从原理到实操完整走一遍。

1. 项目整体设计与思路拆解

1.1 为什么需要“三件套”而不是一个平台

很多团队一开始的诉求是“找个工具把日志管好”,于是上了 ELK;后来要做接口性能分析,又上了 SkyWalking;再后来要监控 CPU、内存和业务指标,又引进了 Prometheus。最后的结果往往是:一个系统里有三套互不相通的监控工具,排查问题时三边来回切换,反而降低了效率。

我个人的观点是,可观测性的核心不是“收集数据”,而是“关联数据”。日志告诉你“发生了什么”,指标告诉你“系统整体有多健康”,链路追踪告诉你“一次请求的完整路径和耗时分布”。只有把这三者通过同一个请求上下文串起来,才能真正做到“从一条慢请求追溯到具体是哪行代码、哪个 SQL、哪台机器出了问题”。

所以这次选型的关键点不是“哪个工具最好用”,而是“如何用一个统一的标准把三者打通”。OpenTelemetry 就是这个“统一标准”,OTLP 是它的传输协议,而 Jaeger、Prometheus、Loki 各自扮演存储与查询的角色。

1.2 工具选型:为什么是 Jaeger + Prometheus + Loki

先看链路追踪。Jaeger 是 CNCF 孵化的分布式追踪系统,原生支持 OpenTelemetry 的 OTLP 协议,可以直接接收 span 数据而无需额外转换层。对比 Zipkin,Jaeger 在 UI 的丰富度和搜索能力上更胜一筹,特别是对多服务链路的依赖图分析,实操体验更好。

再看指标监控。Prometheus 在云原生领域几乎是事实标准,Spring Boot 应用暴露的/actuator/prometheus端点可以直接被抓取。配合 Alertmanager 做告警,再配合 Grafana 做可视化面板,整个链路非常成熟。唯一需要注意的是 Prometheus 是“拉取模型”,需要在网络层面确保可达性,这一点在 Docker Compose 部署中没有任何障碍。

最后是日志聚合。Loki 相比 ELK 最大的优势是“只索引标签,不索引全文”,这意味着资源消耗和存储成本至少低一个数量级。配合 Promtail(现在常见的是 Grafana Alloy)采集日志,通过标签与 LogQL 查询即可完成大部分日志排查需求。最关键的是,Loki 支持按trace_id检索日志,这是实现“日志与链路关联”的核心能力。

1.3 核心流程与整体架构

整个数据流可以这样理解:Spring Boot 应用通过 OpenTelemetry Java Agent(或者 Micrometer Tracing)将三类数据以 OTLP 协议发送出去。链路追踪数据(Span)发送到 Jaeger 的 OTLP 接收端口(默认 4317/4318);指标数据(Metric)既可以通过 OTLP 发送到 Prometheus,也可以通过 Prometheus 直接抓取/actuator/prometheus端点;日志数据则由 Loki 的客户端(如 Grafana Alloy)采集,并在日志中注入trace_id和span_id字段。

读到这里的读者可能会问:为什么日志不走 OTLP?严格来说,OpenTelemetry 的 Logs Signal 也支持 OTLP 传输,但 Loki 生态中最成熟、最稳定的方案仍然是 Alloy 采集文件日志。所以我的建议是:链路和指标走 OTLP,日志走 Alloy + Loki,这是一种兼顾标准与成熟的折中方案。

2. 从 OpenTelemetry 到 OTLP:你需要理解的核心原理

2.1 OpenTelemetry 到底是什么

OpenTelemetry 是一套开源的可观测性标准和工具集,它统一了指标、日志、链路追踪三类数据的采集、处理和传输规范。它的目标很明确:你只需要接入一次 SDK 或 Agent,就能把数据发给任何支持 OTLP 的后端,而不需要为每一个后端单独写一套采集代码。

在 Spring Boot 项目中,接入 OpenTelemetry 有两种常见方式。第一种是使用 OpenTelemetry Java Agent(一个 JVM 启动参数即可),它能自动增强常见框架的埋点,比如 Spring MVC、RestTemplate、JDBC、Kafka 等。第二种是集成 Micrometer Tracing + Micrometer Observation,这是 Spring Boot 3.x 官方推荐的方案,适合需要细粒度自定义埋点的场景。

实测下来,大多数业务团队没有必要从零引入 OpenTelemetry SDK 手工创建 Span。直接用 Java Agent 或者 Micrometer Tracing 自动埋点,覆盖度已经非常高。只有在需要追踪异步线程、消息队列内部任务、自定义业务方法耗时的时候,才需要手写少量代码。

2.2 OTLP 协议为什么是连接所有组件的桥梁

OTLP(OpenTelemetry Protocol)是 OpenTelemetry 定义的传输协议,支持 gRPC(4317 端口)和 HTTP/Protobuf(4318 端口)两种方式。gRPC 的传输效率更高,HTTP 的调试更简单。如果你的服务之间还有防火墙或网关代理,HTTP 方式往往更省心。

OTLP 的设计目标是“一次采集,多端投递”。这意味着你的应用不需要关心数据最终走向 Jaeger 还是 Prometheus,只需要把数据发到一个 OTLP Collector(OpenTelemetry Collector),由 Collector 负责路由和分发。但在资源有限或者场景简单的测试环境中,可以跳过 Collector,让应用直接把 OTLP 数据发送到 Jaeger,指标由 Prometheus 直接抓取,日志由 Alloy 单独采集。这种简化路径在中小型项目中完全可行。

我建议你的项目按“无 Collector 起步,后续按需引入”的思路演进。第一版先把数据跑通,等引入了多环境、多租户、数据过滤或采样等需求时,再在应用与后端之间加入 OpenTelemetry Collector 进行统一处理。

3. 实战准备:环境搭建与工具链版本说明

3.1 Spring Boot 版本选择的个人建议

严格来说,截至目前 Spring Boot 4 尚未正式发布,最新的稳定版本线是 Spring Boot 3.x(如 3.4.x、3.5.x)。标题中的“Spring Boot 4”更可能代表一种对未来的预期,或者是团队内部的版本规划。从实操角度,本文的接入方式对 Spring Boot 3.2+ 和当前最新版本完全适用,如果未来 Spring Boot 4 发布,只要它保留 Actuator 与 OTLP 的自动配置能力,操作路径基本一致。

因此我在本文中默认使用Spring Boot 3.5.x + Java 21。如果你的项目还在用 Spring Boot 2.x,需要额外注意:2.x 中 OpenTelemetry 接入建议直接使用 Java Agent,因为 Micrometer Observation 的自动配置能力不如 3.x 完善;迁移到 3.x 后,代码层面几乎不需要改动,只要替换依赖即可。

3.2 基础设施部署:Docker Compose 一键拉起

为了让教程可复现且不依赖 K8s 环境,这里使用 Docker Compose 部署 Jaeger、Prometheus、Loki、Grafana 和 Grafana Alloy。K8s 部署方式本质上就是把这些组件换成 Deployment 和 Service,配置逻辑完全一致。

下面这份 docker-compose.yml 是我在本地环境实测可用的版本。注意版本号选择:Jaeger 使用 2.x 的jaegertracing/jaeger镜像(内置 OTLP 接收器与 UI);Prometheus 使用 2.53+;Loki 使用 3.x;Grafana 使用 11.x;Alloy 使用 v1.x。

services: jaeger: image: jaegertracing/jaeger:2.6 ports: - "16686:16686" # Jaeger UI - "4317:4317" # OTLP gRPC - "4318:4318" # OTLP HTTP environment: COLLECTOR_OTLP_ENABLED: "true" prometheus: image: prom/prometheus:v2.53.0 ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro loki: image: grafana/loki:3.2.1 ports: - "3100:3100" command: -config.file=/etc/loki/local-config.yaml alloy: image: grafana/alloy:v1.4.2 ports: - "4319:4319" volumes: - ./alloy/config.alloy:/etc/alloy/config.alloy:ro - ./app-logs:/var/log/apps command: run --server.http.listen-addr=0.0.0.0:4319 /etc/alloy/config.alloy grafana: image: grafana/grafana:11.3.0 ports: - "3000:3000" environment: GF_SECURITY_ADMIN_PASSWORD: "admin"

启动命令很简单:在docker-compose.yml所在目录执行docker compose up -d。首次拉取镜像可能需要几分钟,建议提前确认网络环境通畅。

3.3 Prometheus 与 Alloy 配置要点

Prometheus 的配置文件prometheus.yml中最关键的是抓取目标配置。Spring Boot 应用暴露指标的位置是/actuator/prometheus,因此配置如下:

scrape_configs: - job_name: "spring-boot-app" metrics_path: "/actuator/prometheus" static_configs: - targets: ["host.docker.internal:8080"]

这里有一个小坑:容器内的 Prometheus 访问宿主机上运行的 Spring Boot 服务时,不能直接用localhost,而应该使用host.docker.internal。如果你把 Spring Boot 应用也容器化了,则直接写服务名即可。

Alloy 的配置稍复杂一些。核心功能有两个:一是读取 Spring Boot 应用的日志文件,转发到 Loki;二是自动解析日志中的trace_id字段(如果有),方便 Grafana 做数据关联。一个简化但可用的config.alloy配置如下:

loki.write "default" { endpoint { url = "http://loki:3100/loki/api/v1/push" } }

如果后续你想实现“从 Jaeger 跳转到 Loki 查看日志”的一体化体验,必须在 Alloy 的日志处理阶段增加日志标签解析逻辑。我在实战中是这样做的:在日志输出格式中统一加入trace_id和span_id,然后由 Alloy 提取这些字段作为 Loki 的索引标签。这样在 Grafana Explore 里直接根据trace_id查日志,串联整个排查链路。

3.4 Grafana 数据源接入

Grafana 启动后,访问http://localhost:3000,使用admin/admin登录。在“Connections → Data sources”页面依次添加:

  • Jaeger,URL 填http://jaeger:16686
  • Prometheus,URL 填http://prometheus:9090
  • Loki,URL 填http://loki:3100

添加完成后,先不要急着创建 Dashboard。建议先在 Explore 页面分别验证三类数据是否已经能够正常查询,确认数据流之后再投入精力做面板设计。

4. Spring Boot 应用接入:代码层的完整实操过程

4.1 引入依赖与基础配置

以 Maven 项目为例,在pom.xml中增加以下依赖:

<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-tracing-bridge-otel</artifactId> <version>1.3.4</version> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> <version>1.43.0</version> </dependency> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

然后是application.yml中的关键配置。我一开始的时候在这里踩了不少坑,特别是management.otlp.tracing.endpoint的路径写法。这里的 endpoint 应该写成 OTLP gRPC 的地址(注意是 http 前缀,实际是 gRPC 协议),例如:

management: tracing: sampling: probability: 1.0 otlp: tracing: endpoint: http://localhost:4317 endpoints: web: exposure: include: "*" metrics: tags: application: ${spring.application.name}

如果确认网络环境支持 gRPC over HTTP/2 存在障碍,也可以改用 HTTP 协议,将地址改为http://localhost:4318/v1/traces。

配置完成后启动应用,观察控制台日志中是否出现 OTLP 相关的导出日志,同时打开 Jaeger UI(http://localhost:16686),在 Service 下拉框中应该能看到你的应用名。

4.2 日志中注入 trace_id:打通链路与日志的关键一步

如果只做链路追踪,上面两步已经够用了。但要让 Jaeger 中的某一条 Trace 能直接关联到对应的 Loki 日志,必须让日志输出中包含trace_id和span_id,并且这两个 ID 必须来自当前请求对应的 Span。

在 Spring Boot 3.x 中,可以通过在logback-spring.xml中定义带 MDC 的 Pattern 来实现。基于我实际验证过的配置,你需要在logback-spring.xml中加入如下 Pattern:

<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] [%logger{36}] trace_id=%X{trace_id} span_id=%X{span_id} - %msg%n</pattern>

trace_id和span_id会被自动填充,前提是 Micrometer Tracing 正确把 MDC 上下文传递到了日志框架。如果你发现%X{trace_id}输出为空,多半是缺少了micrometer-tracing-bridge-otel依赖,或者是日志格式没有启用 MDC 属性。

这个细节是整个可观测性平台是否“可用”的分水岭。Trace ID 关联不上日志,Jaeger 和 Loki 之间就是两个孤岛;关联上了,排查效率是数量级的提升。

4.3 自定义 Span:监控业务关键操作

自动埋点对框架层面的请求已足够,但它不会告诉你“下单流程中的库存扣减耗费了多久”这类业务级信息。要监控这类关键业务操作,你需要手动创建 Span。

import io.micrometer.tracing.Span; import io.micrometer.tracing.Tracer; import org.springframework.stereotype.Service; @Service public class OrderService { private final Tracer tracer; public OrderService(Tracer tracer) { this.tracer = tracer; } public void createOrder(OrderRequest request) { Span span = tracer.nextSpan().name("order.create").start(); try (var ignored = tracer.withSpan(span)) { // 业务逻辑:库存扣减、价格计算、订单持久化 span.event("inventory.deducted"); } finally { span.end(); } } }

在 Jaeger 的 Trace 详情页里,你能看到order.create这个 Span 以及与它关联的子 Span。如果这个操作成为性能瓶颈,就能明确看到耗时分布在哪一步。

4.4 结合虚拟线程:Java 21 下的可观测性注意点

近期 Java 21 加持下的 Spring Boot 3.5 已经支持虚拟线程,Tomcat 的请求处理线程可以被虚拟线程替代,大幅提升高并发场景下的吞吐量。我观察到很多刚迁移到虚拟线程的团队会遇到一个隐蔽问题:链路追踪上下文在异步边界丢失。

原理很简单:虚拟线程的使用意味着请求处理不再是“一个线程从头跑到尾”,任务可能被多个虚拟线程调度执行。如果埋点体系仍然依赖ThreadLocal传递 TraceId,那么换线程之后上下文就断了。Micrometer Tracing 对大部分框架已经做了上下文传播处理,但自定义的@Async方法、线程池任务、消息监听器仍然需要注意。

最稳妥的做法是尽量避免在@Async或者CompletableFuture内部手动创建 Span,而是从外部传入 TraceId,由子线程通过tracer.nextSpan()关联父级上下文。如果你用的是@Async+ 自定义线程池,还可以考虑在 Executor 的包装层中加入 Trace 上下文传播,但这会增加复杂度,建议业务团队先做验证,再决定是否全局推广。

5. 指标体系构建:从 JVM 到业务指标

5.1 基础指标的开箱即用

接入 Actuator 和 Prometheus 后,你至少可以获得以下指标:

  • JVM 内存使用(堆内、堆外、Metaspace)
  • GC 次数与耗时
  • 线程池活跃线程数
  • HTTP 请求次数、耗时、错误率
  • 数据库连接池使用情况

这些指标无需写一行业务代码。在 Grafana 中,有很多现成的 Spring Boot Dashboard(如 4701、12900),导入后稍作数据源调整就能用。对多数团队来说,先把这些基础指标监控起来,已经能覆盖“服务是否健康”这个核心问题。

5.2 自定义业务指标(Counter 与 Gauge)

基础指标解决“系统层面”的监控,但业务指标同样重要。比如想知道“每分钟成功下单量”或者“当前排队任务数”,你可以用 Micrometer 直接构造指标。

import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.MeterRegistry; import org.springframework.stereotype.Component; @Component public class OrderMetrics { private final Counter orderCreated; private final Counter orderFailed; public OrderMetrics(MeterRegistry registry) { this.orderCreated = Counter.builder("order.created.total") .description("Total number of created orders") .register(registry); this.orderFailed = Counter.builder("order.failed.total") .description("Total number of failed orders") .register(registry); } public void recordCreated() { this.orderCreated.increment(); } public void recordFailed() { this.orderFailed.increment(); } }

Counter 用于单调递增的计数场景(比如总请求数)。若你想监控当前在途订单、队列长度这类“可增可减”的数值,则应该使用 Gauge。Gauge 的注册方式是传一个实际的数值提供者,例如:

Gauge.builder("order.queue.size", queue, List::size) .register(registry);

这里需要注意的是,Gauge 会实时获取当前值,你不应该手动去修改它的值,只要底层数据源变化,Gauge 就会跟着变化。

5.3 Histogram:监控延迟分布

监控接口耗时,平均值是一个有很大迷惑性的指标(极端值可能被平均数掩盖)。推荐使用 Histogram 来记录请求耗时的分布情况。

registry.timer("http.request.duration", "application", "order-service", "endpoint", "/api/v1/orders") .record(Duration.ofMillis(123));

在 Prometheus 中会对应生成http_request_duration_seconds_bucket、_sum、_count等序列。配合 PromQL 中的 Histogram Quantile 函数(比如histogram_quantile(0.95, sum(rate(...) by (le)))),可以精确计算 P95、P99 耗时。

P99 是一个比平均值更值得关注的指标。我在实际运维中见过不少“平均耗时 50ms,但 P99 超过 2 秒”的服务,这类服务一旦流量波动,很容易触发超时连锁反应。建议把 P99 作为核心监控指标,并设置对应的告警阈值。

6. 链路追踪深度使用:从“能看到”到“能用好”

6.1 服务间调用的全链路串联

如果你只有一个 Spring Boot 服务,链路追踪的威力并不明显。但只要有服务 A 调用服务 B,再调用服务 C,链路追踪就变得极具价值。在 OpenTelemetry 体系中,下游服务会自动从 HTTP 头(如traceparent)中提取 TraceId,从而串成完整的 Trace。

一个常见的实际场景是:Gateway 收到请求后转发到订单服务,订单服务通过 RestClient 调用库存服务,同时异步发送消息到 Kafka 消费队列。如果三个服务都接入了 OpenTelemetry,你在 Jaeger 中看到的是一条完整体现调用关系的链路,每个节点的耗时清清楚楚,哪个环节慢一目了然。

这里值得注意的一点是:只有所有服务都使用同一种且兼容的追踪协议时,跨服务链路才能保证连通。如果 A 服务用 SkyWalking,B 服务用 Jaeger,即使它们都实现了 W3C Trace Context 规范,标准不一致也容易导致 Trace 断裂。所以团队内部尽量统一标准是非常必要的,OpenTelemetry 恰好就是那个“公约数”。

6.2 采样策略:兼顾数据完整性与性能开销

每次请求都创建完整的 Trace 数据,在低流量场景下没问题,但在高并发场景下,存储成本和性能开销会迅速上升。这时需要采样策略。

OpenTelemetry 支持三种典型的采样方式:

  • 始终采样:probability=1,适合开发和测试环境。
  • 概率采样:probability=0.1,即 10% 的请求被记录,适合生产环境。
  • 尾部采样:需要引入 Collector 和额外策略,根据链路结果决定是否保留,适合复杂链路分析。

生产环境建议先按 10% 的概率采样起步。这样既能看到绝大多数问题的链路现场,又不会把存储打爆。在排查特定问题时,临时把某个服务的采样率调到 100% 也是比较常见的操作。

6.3 用 Jaeger UI 定位性能瓶颈

Jaeger UI 的 Trace 详情页提供了火焰图(Flame Graph)视图,每个 Span 以条状形式展示,长度对应耗时。从火焰图上你可以直观看出请求时间都消耗在哪里。

当你发现某个 SQL 操作的 Span 耗时异常高,但无法从链路图判断是否是数据库本身的问题时,可以跳转到日志:在 Jaeger 详情页可以看到每条 Trace 的标签信息,如果你的日志中注入了 trace_id,那么直接在 Grafana 的 Explore 里按 trace_id 搜日志,看看那个时间段数据库连接池是否有异常、GC 是否频繁、或者是否有慢查询。

这种“链路定位边界,日志定位细节”的排查方式是整个平台的核心价值。链路追踪告诉你问题在哪一层的哪一个调用上;日志告诉你具体原因;指标告诉你影响面有多大。三者组合,多数线上疑难杂症都能在几分钟内定位到代码级。

7. Loki 日志聚合:从 ELK 迁移的体验与配置细节

7.1 Loki 与 ELK 的本质差异

Loki 与 ELK 在架构上有很大不同。ELK 中的 Elasticsearch 会对日志全文建立索引,因此查询灵活但成本高;Loki 则只对日志的标签(如app、namespace、pod、level)建索引,日志内容本身不建立索引,而是通过 LogQL 先按标签缩小范围,再对范围内的日志做过滤匹配。

这带来的直接影响是:如果你不按标签筛选而直接全文搜索,Loki 的查询会比较慢。所以在 Loki 体系里,标签设计是第一优先级。按什么维度打标签直接决定了日志检索的效率和成本。

我前面提到的trace_id、span_id就是高价值的标签。在 Alloy 中,可以通过stage.json或者stage.regex提取日志中的字段为标签,然后在 Loki 内通过{app="order-service"} |= "error"这类语法查询,或者直接用trace_id精确锁定某一次请求的所有日志。

7.2 Alloy 采集配置详解

Grafana Alloy 是 Promtail 的继任者,配置方式从 YAML 改成了类似 HCL 的语法。一个能用的最小配置,需要包含三部分:日志源读取、日志解析、写入 Loki。

logging { level = "info" } loki.source.file "app_logs" { targets = [] forward_to = [loki.write.default.receiver] file { path_pattern = "/var/log/apps/*.log" } } loki.process "app_logs" { stage.regex { source = "message" regex = "trace_id=(?P<trace_id>[\\w+-]+)" } stage.labels { values = { trace_id = "", } } forward_to = [loki.write.default.receiver] } loki.write "default" { endpoint { url = "http://loki:3100/loki/api/v1/push" } }

上述配置会把/var/log/apps/*.log中匹配到的trace_id作为 Loki 的标签。这样当你从 Jaeger 中获取某个 Trace ID 之后,在 Grafana 中执行{app="order-service"} |= "trace_id=xxx",就能一次性找到该请求的全链路日志。

7.3 日志内容规范:别让 Laconic 日志成为排查瓶颈

即便基础设施都打通,如果应用本身的日志内容质量不高,聚合后的价值也有限。建议把至少以下信息强制写入日志:

  • 时间戳:精确到毫秒。
  • 日志级别:DEBUG / INFO / WARN / ERROR。
  • TraceId / SpanId:用于请求链路关联。
  • 关键上下文:订单号、用户 ID、请求路径等。
  • 业务状态:成功 / 失败 / 超时。

一条有质量的生产日志,应该能在不阅读业务代码的情况下,让人大概猜出当时发生了什么。这一点在排查问题时帮助巨大。

8. 三大模块一体化:Grafana 面板与告警配置

8.1 Grafana 多渠道数据源联动

Grafana 最重要的能力是能把 Prometheus 和 Loki 的数据放在同一个 Dashboard 上联动展示。比如上方是服务 P99 延迟趋势图,下方是同一时间段的 ERROR 日志列表。当延迟跳变时,你可以直接看到错误日志是不是同步增多,而不需要切来切去。

实际操作技巧:在 Grafana 的 Panel 编辑中,可以对 Prometheus 数据源的查询加入变量(比如application、endpoint),再把变量同步给日志 Panel,这样整个 Dashboard 就形成了统一的筛选联动。

8.2 用 PromQL 编写核心监控告警

我建议优先级最高的告警项包括以下几类:

  • 服务不可用(up == 0)
  • 请求错误率超过阈值(sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) / sum(rate(http_server_requests_seconds_count[5m])) > 0.05)
  • 接口 P99 耗时超过红线(histogram_quantile(0.99, sum(rate(..._bucket[5m])) by (le)) > 1000)
  • JVM 老年代内存使用率持续高位

告警通知渠道方面,Grafana 支持钉钉、企微、Slack、Webhook 等。生产环境建议把告警接工单系统,开发环境建议只需要推送到 IM 群即可。频繁误报会影响团队对告警的重视程度,所以告警阈值宁可先放宽,也不要“狼来了”。

8.3 自定义可视化 Dashboard 的建议

很多团队会去下载现成的 Dashboard JSON,但这往往不是最优做法。原因很简单:现成模板的指标命名和标签未必匹配你的业务场景。更好的做法是:先梳理应用的核心关注项(QPS、P99、错误率、JVM 内存、SQL 慢查询),然后再逐项找指标、建面板。

建议每个业务服务至少有一个专属 Dashboard,包含四行内容:第一行是“请求量 / 错误率 / P99”,第二行是“JVM 内存 / GC”,第三行是“数据库连接池 / 缓存命中率”,第四行是“近期错误日志摘要”。这种精简但聚焦的布局比一次性堆砌几十个面板实用得多。

9. 常见问题与排查技巧实录

我在多个项目里落地这套方案,几乎每次都会遇到几个高频问题。这里整理成速查表,能帮你省不少时间。

现象可能原因排查建议
Jaeger UI 看不到服务列表OTLP endpoint 配置错误,或采样概率为 0检查management.otlp.tracing.endpoint,确认端口是否为 4317/4318
日志中 trace_id 为空缺少 Micrometer Tracing Bridge 依赖,或日志 Pattern 不含 MDC确认依赖micrometer-tracing-bridge-otel存在,检查 logback pattern 中%X{trace_id}
Prometheus 抓不到 /actuator/prometheusActuator 端点未暴露,或防火墙阻止检查management.endpoints.web.exposure.include=*,并确认网络可达
Loki 日志有延迟Alloy 的 tail 配置延迟,或标签过多导致写入慢检查 Alloy 日志,合理设计标签数量(不要超过 10 个)
跨服务调用 Trace 断裂下游服务未接入 OpenTelemetry,或协议不统一确保所有服务都通过 OTLP 接入,统一使用traceparent头传递上下文
Docker 容器内访问宿主机应用失败使用了 localhost / 127.0.0.1使用host.docker.internal替代
Prometheus 指标出现 1 分钟空白抓取周期过长,或应用死锁检查scrape_interval,观察应用日志是否有 OOM 或 Full GC

还有一个值得单独提出的问题:OTLP gRPC 连接不稳定。部分环境对 HTTP/2 支持不好,出现间歇性断连。此时可以将 exporter 改为 HTTP 方式,即 endpoint 设置为http://localhost:4318/v1/traces,稳定性和调试便利性都会有明显提升。

在实际操作中,把整套链路跑通往往只需要半天时间,真正的挑战在于数据质量:日志格式是否规范、关键指标是否覆盖、Trace 上下文是否顺畅传递。建议按“先链路,再日志,后指标”的顺序推进。链路追踪能最快看到效果,日志关联是排查效率的关键,指标监控则决定你是否能在问题发生前预警。

再分享一个小技巧:在 Grafana 中为 Loki 和 Jaeger 数据源开启“混合数据源”模式,把日志和链路放在同一面板。当你盯着一张图就能完成“从高延迟指标到具体 Trace 再到具体日志”的完整下钻时,可观测性平台才算是真正建好了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/26 5:38:16

系统集成十年演进:从机房堆叠到工业机器人系统集成

有个做售前的朋友前两天问我&#xff1a;“你说咱们这个系统集成行业&#xff0c;到底还算不算一个行业&#xff1f;”我当时愣了半天。要说算吧&#xff0c;现在的大项目动辄就是云原生化、软件定义一切&#xff0c;那种传统“搬服务器、拉网线、装系统”的集成活儿&#xff0…

作者头像 李华
网站建设 2026/9/26 5:37:08

视觉工件尺寸测量:从标定到亚像素边缘提取的微米级精度实战

简介&#xff1a;这份资源围绕计算机视觉在工件尺寸测量中的应用展开&#xff0c;面向从事工业检测、自动化产线或机器视觉方向的学习者与工程人员&#xff0c;帮助理解如何用图像处理替代传统卡尺、千分尺等接触式量具&#xff0c;解决批量生产中尺寸检测效率与精度问题。压缩…

作者头像 李华
网站建设 2026/9/26 5:36:52

Flash Attention实战避坑指南:四款大模型推理压测深度解析

1. 这不是“模型评测”&#xff0c;而是一场面向真实部署场景的Flash推理压力测试最近两周&#xff0c;我连续在三类不同规格的机器上跑了四轮完整实测&#xff1a;一台32GB内存RTX 4090的开发工作站、一台64GB内存双A100 80G的推理服务器、还有一台用MacBook Pro M3 Max临时搭…

作者头像 李华
网站建设 2026/9/26 5:36:20

Canal原理与实战:MySQL实时同步到ES、Redis、Kafka

做了几年数据同步&#xff0c;MySQL主库到从库、到ES、到Redis、到数仓&#xff0c;各种折腾。今天把Canal这套东西掰开揉碎讲清楚。Canal是阿里巴巴开源的一个中间件&#xff0c;核心原理是把自己伪装成一个MySQL的从库&#xff0c;订阅主库的Binlog日志&#xff0c;然后把增量…

作者头像 李华
网站建设 2026/9/26 5:34:47

秦皇岛越野叉车生产厂家挑选全攻略,北叉重工信誉度高广受信赖

北叉重工(天津)有限公司是长期深耕越野叉车研发、生产与工况适配的实体制造品牌&#xff0c;始终聚焦野外非铺装路面的搬运作业难题&#xff0c;依托11000平方米标准化生产厂区搭建独立的越野叉车研发与装配生产线&#xff0c;打造多吨位、多机型、高适配的越野叉车产品体系&am…

作者头像 李华