ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Spring Boot整合Prometheus+Grafana:从0到1构建业务自定义指标监控

Spring Boot整合Prometheus+Grafana:从0到1构建业务自定义指标监控

做了这么多年后端开发,我越来越确定一件事:监控系统不是上线以后再补的,而是写代码的时候就要想清楚的。过去我经历过不少次线上事故,CPU、内存、磁盘这些基础设施指标看着都正常,但业务就是不对——订单量悄悄掉了没人发现,某个接口延迟越来越高但系统资源却"毫无波澜"。后来我把Spring Boot应用接入了Prometheus和Grafana,用自定义指标把业务状态彻底透明化,才真正解决了"资源正常但业务出问题"这种最磨人的故障。

这篇文章就围绕Spring Boot整合Prometheus+Grafana做自定义指标监控,从选型思路、环境搭建、指标原理,到实际埋点、面板展示和告警配置,完整走一遍。我用的都是实际踩过坑之后落定的方案,代码可以直接抄,配置直接复制就能跑起来。

1. 为什么业务监控不能只靠系统资源指标

1.1 一次深夜事故给我的教训

先讲一个真实发生在我项目里的案例。

某个核心订单服务的实例,当时故障表现是:接口不报错,但订单创建成功率直线下降。我收到告警时,先看CPU、内存——CPU 30%,内存用了不到60%,磁盘IO也很平稳,一切看起来都"很健康"。可实际上,前端反馈用户下单总失败。

我排查了将近一小时,最后发现是某个下游服务的连接池被占满,导致新请求全部卡在等待连接的状态,接口RT飙升但服务本身资源占用并不高。如果当时我监控了"订单创建耗时"这个业务指标,第一眼就能看到RT异常,再顺着链路去找原因,整个过程用不了五分钟。

这次事故之后,我的监控理念彻底变了:系统资源指标是"底层保障",业务指标才是"真实效果"。你上线一个订单服务,最终好不好用,不是看CPU多少,而是看订单能不能成功创建、耗时多少、积压了多少。

1.2 基础设施指标和自定义业务指标的本质区别

系统资源指标通常指CPU、内存、磁盘、网络等,它们描述的是"机器状态"。而自定义业务指标描述的是"业务健康度",两者分层明显:

维度系统资源指标自定义业务指标
关注对象服务器、容器、中间件业务流程、用户行为、服务质量
代表指标CPU使用率、内存使用率、磁盘IO订单成功率、下单耗时、积压消息数
故障表现机器过载时才异常业务出问题时可能资源一切正常
告警时机资源告警往往滞后业务指标告警更接近"真实故障时刻"

说白一点:系统资源指标是"消防车",业务自定义指标是"火灾探测器"。你当然不能没有消防车,但真正帮你第一时间发现火灾的,还是探测器。

1.3 什么场景适合用自定义指标监控

经验来看,下面几类场景特别值得做自定义指标:

  • 核心业务链路:订单创建、支付回调、消息消费,这些是"命脉"指标,必须实时盯。
  • 外部依赖稳定性:下游接口调用量、调用耗时、失败次数,能快速判断是谁拖慢了整体链路。
  • 队列与异步任务:消息积压数量、消费速率、重试次数,是排查削峰填谷问题的高频切入点。
  • 特殊业务时段:比如秒杀活动、抢购场景,瞬时流量和峰值吞吐,需要更细粒度的指标来观测。

这些场景,光靠Spring Boot默认暴露的health、info这些端点远远不够,必须自己定义指标,让Prometheus采集到有业务语义的数据。

2. 技术选型:为什么是Prometheus+Grafana这套组合

2.1 主流监控方案横评

市面上可用的监控方案不少,但真正适合"Spring Boot应用+自定义业务指标"这个场景的,我筛下来也就几个:

方案优点缺点适合场景
Prometheus + Grafana云原生标准、Pull模型、社区生态强、告警灵活不支持复杂长时间存储,需要额外组件做持久化微服务、K8s、自定义指标丰富的场景
Zabbix部署简单、模板丰富指标模型偏基础设施,自定义业务指标比较笨重传统IT设备监控
SkyWalking分布式链路追踪强,自带拓扑图指标监控能力相对弱,重链路不重度量APM专项场景
开源时序库+自研灵活度高投入大、维护成本高超大团队才会考虑

我最终选择Prometheus+Grafana的核心原因有三个:

  1. Pull模型更契合微服务架构。每个Spring Boot应用暴露一个/actuator/prometheus端点,Prometheus定期拉取,服务和监控解耦,新服务注册其实就是加一行配置。
  2. 指标模型强大。标签(Label)体系让同一个指标可以按各种维度(接口、方法、状态码、区域)切片分析。
  3. Grafana的生态太成熟了。面板社区里有大量开箱即用的模板,截图汇报、告警渲染、多数据源联动都很顺手。

2.2 Pull模型和Push模型的哲学差异

很多刚接触监控的读者容易疑惑:为什么Prometheus不去"收集"数据,而是让应用"暴露"数据等它来拉?

打个比方:Push模型就像快递员上门取件,每个应用主动把数据送到监控中心;Pull模型则是监控中心定时到每个应用家门口"取件"。Pull模型的好处是——监控系统不会成为消息堆积的牺牲品,也不会因为某个应用突发巨量数据而被冲垮。另外Pull模型天然能检测"应用是否活着":拉不到数据就说明应用挂了,这本身就是一种指标。

当然Pull模型也有缺点:如果应用和Prometheus网络隔离,或者应用是短生命周期任务(批处理作业),Pull就不方便。这种场景可以用Pushgateway做补充,但常规Spring Boot服务基本都是长驻进程,Pull完全够用。

2.3 时间序列模型带来的统计计算便利

Prometheus底层存储的是"时间序列数据",每个序列由指标名+标签集唯一标识,值随时间不断累加。这种模型的强大之处在于,做统计分析不需要原始明细数据,直接在时间序列上就能完成:

  • 计算"每秒订单创建速率":直接用rate(order_created_total[5m])
  • 计算"接口95分位延迟":直接用histogram_quantile(0.95, sum(rate(order_process_seconds_bucket[5m])) by (le))
  • 计算"积压订单变化趋势":直接用delta(order_backlog[10m])

这些函数在PromQL里都是内置的,不用我们写任何代码。对比传统的SQL聚合,或者自己写统计逻辑,效率差距不是一星半点。

3. 环境搭建:Spring Boot应用接入Actuator和Micrometer

3.1 pom.xml依赖引入

现在Spring Boot和Prometheus的整合已经非常顺滑,核心角色是Micrometer——它是JVM生态的指标门面框架,类似SLF4J之于日志。Micrometer定义了一套统一指标模型,Prometheus只是它的一个"后端实现"。

我这边用的是Spring Boot 2.x,做过好几个版本适配,最稳定的依赖组合如下:

<dependencies> <!-- Spring Boot Actuator:端点暴露 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Micrometer Prometheus 注册器 --> <dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency> </dependencies>

不用手动指定Micrometer的版本号,Spring Boot的dependency management会自动选一个兼容的版本。如果你用的是Spring Boot 3.x,引入方式一模一样,只是底层换成了Micrometer 1.x以上的版本,API基本兼容。

3.2 核心配置项与暴露策略

引入依赖之后,要在application.yml里把Prometheus的端点暴露出来。这里有一个新手经常掉的坑:Actuator默认只暴露health和info两个端点,你如果不显式配置,/actuator/prometheus会一直返回404。

management: endpoints: web: exposure: include: health,info,prometheus,metrics endpoint: health: show-details: always metrics: export: prometheus: enabled: true tags: application: order-service

几个比较关键的点:

  • include: health,info,prometheus,metrics,这里面prometheus是必须的,metrics方便你调试查看JVM等默认指标。
  • management.metrics.tags.application会给所有指标统一加上application="order-service"这个标签。这是我在多服务混部场景下强烈建议加的,否则Grafana面板里多个服务的指标会纠缠在一起,无法按服务过滤。

如果你用的是Spring Boot 3.x,部分配置路径可能略有调整,但整体结构一致。

3.3 验证Spring Boot应用是否成功暴露指标

启动应用后,先访问http://localhost:8080/actuator/prometheus,浏览器里如果能看到一大片以# HELP和# TYPE开头的文本,说明指标暴露已经成功了。比如:

# HELP jvm_memory_used_bytes The amount of used memory # TYPE jvm_memory_used_bytes gauge jvm_memory_used_bytes{area="heap",application="order-service",id="G1 Survivor Space",} 524288.0

这里面除了JVM的指标,还有HikariCP连接池的指标、Tomcat线程池指标、Spring MVC的请求耗时指标等等。Micrometer做了大量"自动埋点"工作,你什么都不写就已经获得了几十上百个指标。不过这些自动指标只能反映框架层面的情况,真正体现业务状态的指标,还是得自己动手埋。

4. 自定义指标的核心原理:Micrometer指标模型与四种类型

4.1 指标是怎么从业务代码流到Prometheus的

理解了整条链路,后面写代码就不会心存疑虑:

  1. 业务代码调用Micrometer API,给某个指标名赋一个值或执行一次计数。
  2. Micrometer把这个指标写入内存中的寄存器(MeterRegistry)。
  3. Prometheus通过HTTP调用/actuator/prometheus端点,Micrometer把当前内存里的指标快照按Prometheus的文本格式暴露出去。
  4. Prometheus按配置的时间间隔抓取,存入自己的时序数据库。
  5. Grafana通过PromQL查询并渲染成图表。

所以Micrometer是我们业务代码唯一需要接触的API,你不需要直接跟Prometheus的格式打交道。

4.2 Counter、Gauge、Timer、Histogram四种指标类型

Micrometer提供的主要指标类型有四种,理解它们的语义差别,是设计好自定义指标的前提。

Counter(计数器)

只能单调递增,适合统计"发生了多少次"和"总量累计"。比如订单创建总数、支付成功总数、请求失败次数。

Counter orderCreatedCounter = Counter.builder("order.created.total") .description("累计创建订单数") .tag("channel", "app") .register(meterRegistry);

Gauge(仪表盘,可增可减)

适合表示"当前状态值",比如当前积压订单数、当前在线用户数、线程池活跃线程数。Gauge不需要手动设置新值,而是由Micrometer在采集时拉取你提供的Supplier。

AtomicInteger backlogCount = new AtomicInteger(); Gauge.builder("order.backlog", backlogCount, AtomicInteger::get) .description("当前积压订单数") .register(meterRegistry);

Timer(计时器)

专门统计耗时分布。内部会记录调用次数、总耗时、最大耗时,并配合Histogram(直方图)计算耗时分布。比如"下单处理耗时"用Timer最合适。

Timer orderProcessTimer = Timer.builder("order.process.time") .description("下单处理耗时") .publishPercentileHistogram() .register(meterRegistry); long start = System.nanoTime(); try { // 业务逻辑 } finally { orderProcessTimer.record(Duration.ofNanos(System.nanoTime() - start)); }

Histogram(直方图)

更精确地观测数据分布,比如订单金额分布、请求大小分布。它按你预设的桶(bucket)记录落入每个区间的次数。

DistributionSummary orderAmountSummary = DistributionSummary.builder("order.amount") .description("订单金额分布") .baseUnit("yuan") .minimumExpectedValue(1.0) .maximumExpectedValue(10000.0) .publishPercentileHistogram() .register(meterRegistry);

这里面的关键是:Counter和Gauge解决"多少"的问题,Timer和Histogram解决"多慢"和"分布如何"的问题。一个完整的业务监控系统,这四类都会用到。

4.3 标签(Tag)是自定义指标的灵魂

标签是Prometheus最有价值的设计之一。比如同样是订单创建总数,你可以打上channel标签区分App、小程序、H5;打上region标签区分华东、华北;打上status标签区分成功、失败。

我的经验是:标签要克制,尽量控制在3~5个以内。因为Prometheus里每个标签值都是一个独立的时间序列,标签维度爆炸会让存储压力和查询性能都显著上升。比如一张订单表有几十个状态字段,你不可能全做成标签,只挑你最经常做分组统计的维度做标签,其他信息留在日志里即可。

5. 实战:给订单服务制作一套完整的业务监控指标

5.1 定义一个专门封装指标的服务类

我习惯的做法是建一个专门的OrderMetricsService,把跟监控指标相关的代码全部收敛起来。这样做的好处是埋点代码不会散落在业务代码各处,后续要删要改都方便。

@Component public class OrderMetricsService { private final MeterRegistry meterRegistry; private final Counter orderCreatedTotal; private final Counter orderFailedTotal; private final AtomicInteger orderBacklog; private final Timer orderProcessTimer; private final DistributionSummary orderAmountSummary; public OrderMetricsService(MeterRegistry meterRegistry) { this.meterRegistry = meterRegistry; this.orderCreatedTotal = Counter.builder("order.created.total") .description("累计创建订单数") .tag("type", "normal") .register(meterRegistry); this.orderFailedTotal = Counter.builder("order.failed.total") .description("累计创建失败订单数") .tag("type", "normal") .register(meterRegistry); this.orderBacklog = new AtomicInteger(0); Gauge.builder("order.backlog", orderBacklog, AtomicInteger::get) .description("当前积压待处理订单数") .register(meterRegistry); this.orderProcessTimer = Timer.builder("order.process.time") .description("订单处理耗时") .publishPercentileHistogram() .serviceLevelObjectives(Duration.ofMillis(100), Duration.ofMillis(300), Duration.ofMillis(500)) .register(meterRegistry); this.orderAmountSummary = DistributionSummary.builder("order.amount") .description("订单金额分布") .baseUnit("yuan") .minimumExpectedValue(10.0) .maximumExpectedValue(5000.0) .publishPercentileHistogram() .register(meterRegistry); } public void recordOrderCreated() { orderCreatedTotal.increment(); } public void recordOrderFailed() { orderFailedTotal.increment(); } public void incrementBacklog() { orderBacklog.incrementAndGet(); } public void decrementBacklog() { orderBacklog.decrementAndGet(); } public void recordProcessTime(Duration duration) { orderProcessTimer.record(duration); } public void recordOrderAmount(double amount) { orderAmountSummary.record(amount); } }

我特别说一下serviceLevelObjectives这个配置。它让你自定义Timer的"桶"范围,比如100ms、300ms、500ms。不配置也可以,Micrometer默认会生成很多桶,但那种桶的数量很多,存储开销更大。根据自己的业务耗时预期,定制3~5个有业务意义的桶,比默认可视化效果好得多。

5.2 在业务代码里埋点

有了专门封装的服务类,埋点就变得很清爽。在订单创建的主流程里加上统计逻辑:

@Service public class OrderService { private final OrderMetricsService orderMetricsService; // 构造器注入省略 @Transactional public Order createOrder(CreateOrderRequest request) { long start = System.nanoTime(); try { Order order = new Order(); order.setUserId(request.getUserId()); order.setAmount(request.getAmount()); // 其他业务逻辑 orderRepository.save(order); orderMetricsService.recordOrderCreated(); orderMetricsService.recordOrderAmount(request.getAmount()); orderMetricsService.recordProcessTime(Duration.ofNanos(System.nanoTime() - start)); // 订单创建后积压待处理数增加 orderMetricsService.incrementBacklog(); return order; } catch (Exception e) { orderMetricsService.recordOrderFailed(); throw e; } } public void processOrder(Long orderId) { try { // 处理订单逻辑 Thread.sleep(200); } finally { // 处理完成积压数减少 orderMetricsService.decrementBacklog(); } } }

有几个复用点值得说明:

  • recordProcessTime放在finally或者在正常分支里执行都没问题,但如果方法里有多个return路径,最好用try-finally包住时间统计,否则容易漏记某些路径的耗时。
  • 积压数用AtomicInteger配合Gauge,天然适合并发环境下的增减。
  • 失败次数Counter放在catch块里,既统计了失败总数,又不会影响正常流程。

5.3 看板核心指标一步步验证

埋完代码重启应用,再用浏览器访问/actuator/prometheus,你应该能看到类似下面的内容:

# HELP order_created_total 累计创建订单数 # TYPE order_created_total counter order_created_total{application="order-service",type="normal",} 12.0 # HELP order_process_time_seconds 订单处理耗时 # TYPE order_process_time_seconds histogram order_process_time_seconds_bucket{application="order-service",le="0.1",} 5.0 order_process_time_seconds_bucket{application="order-service",le="0.3",} 8.0 order_process_time_seconds_bucket{application="order-service",le="0.5",} 9.0 order_process_time_seconds_bucket{application="order-service",le="+Inf",} 12.0 order_process_time_seconds_count{application="order-service",} 12.0 order_process_time_seconds_sum{application="order-service",} 2.347

注意看Timer在Prometheus结构中是一组指标:_bucket、_count、_sum。这也是为什么Prometheus能直接算P95、P99等分位数——利用histogram_quantile函数配合_bucket数据就能计算。

我自己在验证时有个技巧:先用浏览器直接访问端点,确认格式无误,再配置Prometheus抓取。如果直接跳去配Prometheus,一旦抓不到数据,你是无法判断是Spring Boot端的问题还是Prometheus配置问题的。

6. 配置Prometheus抓取Spring Boot指标

6.1 下载与基础启动

Prometheus是一个独立的进程,它跟Spring Boot应用没有代码耦合。我日常有两种部署方式:

  • 生产环境用Docker Compose编排,方便扩展。
  • 本地开发直接下载二进制包,写一个prometheus.yml,然后./prometheus --config.file=prometheus.yml启动。

Prometheus默认监听9090端口,启动后访问http://localhost:9090就能看到自带的UI,可以做PromQL查询、查看Targets状态。

6.2 prometheus.yml完整配置

我整理了一份能直接用的配置,里面已经注释了关键点:

global: scrape_interval: 15s evaluation_interval: 15s scrape_configs: - job_name: 'spring-boot-app' metrics_path: '/actuator/prometheus' static_configs: - targets: ['192.168.1.100:8080'] labels: instance: 'order-service'

需要解释几个配置项:

  • scrape_interval:抓取间隔。15秒对大部分业务指标都够用,如果要做秒级监控可以调到5秒,但要注意Prometheus存储压力会随之增加。
  • metrics_path:默认是/metrics,Spring Boot Actuator的Prometheus端点是/actuator/prometheus,所以这里必须显式指定。
  • targets:填Spring Boot应用的IP和端口。如果Prometheus和应用在同一个Docker网络里,可以直接填服务名。
  • evaluation_interval:告警规则评估间隔,和抓取间隔保持一致最省心。

6.3 Targets面板确认采集状态

启动Prometheus后,进入Status -> Targets页面,如果配置正确,spring-boot-app这个job的State应该是UP。如果显示DOWN,80%的情况是metrics_path不对,或者网络不通。

我当时踩过一个比较隐蔽的坑:Spring Boot应用开启了服务发现注解但没配端口映射,Prometheus从宿主机抓不到容器内部的8080。排查方法很简单:在Prometheus所在的主机上用curl http://<应用IP>:8080/actuator/prometheus先验证通不通,通不过再去查网络层。

7. Grafana监控面板的搭建与核心图表绘制

7.1 添加Prometheus数据源

Grafana安装完成之后,默认端口3000,第一次登录默认账号admin/admin,之后会要求改密码。数据源配置很简单:

  1. 打开左侧齿轮图标,进入Configuration -> Data sources。
  2. 点击Add data source,选择类型Prometheus。
  3. 在URL字段填Prometheus的地址,比如http://192.168.1.200:9090。
  4. 点击Save & Test,看到绿色提示说明连接成功。

这里有一个常见问题:Grafana是容器部署、Prometheus也是容器部署时,URL不能写localhost:9090,而要写Prometheus容器在Docker网络里的服务名,或者宿主机IP。否则Save & Test会一直报错。

7.2 从零创建业务面板

我比较推荐先自己手动建一两个面板,搞清楚图表的基本逻辑,之后再去社区里找模板导入。

创建面板的具体步骤:

  1. 左侧加号 ->Create -> Dashboard -> Add visualization。
  2. 选择数据源Prometheus。
  3. 在查询编辑器(Query Editor)里输入PromQL。

比如最核心的"订单创建速率"面板,PromQL写:

sum(rate(order_created_total[5m])) by (instance)

画面板配置,几个我自己常用的设置:

  • Legend设为{{instance}},让每条曲线以实例名区分。
  • Unit选为ops/s,数值以每秒次数展示。
  • Min step设为15s,与抓取间隔保持一致,避免图表出现锯齿。

另外,"订单处理耗时P95"也是我最依赖的面板之一,PromQL如下:

histogram_quantile(0.95, sum(rate(order_process_time_seconds_bucket[5m])) by (le))

配合order_process_time_seconds_bucket的直方图数据,这条查询能算出过去5分钟下单耗时的95分位值。看P95而不是看平均值,能极大程度避免"平均耗时正常但长尾请求很慢"的失真情况。

7.3 常见图表类型的选择心得

Grafana图表类型不少,但真正在业务监控里高频使用的就几种:

  • Time series(时间序列图):最常用,适合展示指标随时间的变化趋势,比如订单创建速率、处理耗时。
  • Stat(统计值):只显示当前值或最近值,适合展示"当前积压订单数""今日订单总量"这种一眼要看到结果的指标。
  • Bar chart(柱状图):适合对比不同标签的值,比如各渠道订单量对比。
  • Table(表格):适合展示明细数据,比如各实例各接口的存活状态。

一个面板页面里面混用这几种图表,就足够覆盖90%的监控展示需求了。

8. 告警规则配置与实践中的重点注意事项

8.1 用Prometheus Rule设置告警

Grafana本身也有告警能力,但我更习惯用Prometheus的Alertmanager来做告警规则管理,因为它不依赖Grafana运行,更贴近"基础监控"的定位。

在prometheus.yml所在目录建一个规则文件,比如rules.yml:

groups: - name: order-service-alerts rules: - alert: OrderCreatedRateDrop expr: | sum(rate(order_created_total[10m])) by (instance) < 50 for: 5m labels: severity: warning annotations: summary: "订单创建速率异常下降" description: "实例 {{ $labels.instance }} 订单创建速率最近10分钟低于50次/分钟,请检查业务链路" - alert: OrderProcessTimeHigh expr: | histogram_quantile(0.95, sum(rate(order_process_time_seconds_bucket[5m])) by (le, instance)) > 1.0 for: 3m labels: severity: critical annotations: summary: "订单处理耗时过高" description: "实例 {{ $labels.instance }} 的P95处理耗时超过1秒,持续3分钟"

然后在prometheus.yml里引入这个规则文件:

rule_files: - "rules.yml"

告警的核心是表达式要贴近业务感受。比如订单创建速率下降,低于某个阈值时触发;处理耗时超过1秒持续3分钟触发。这个阈值需要根据业务数据慢慢调,切忌一开始就定一个绝对值,最好先观察一周左右的实际分布再做规则。

8.2 实践中总结的几个"坑"

以下是我在Spring Boot整合Prometheus的过程中真正遇到过的坑,每一个都花了不少时间才解决。

第一坑:指标名被加了后缀

Micrometer会自动统一指标命名。比如我写order.process.time,暴露到Prometheus里会变成order_process_time_seconds。这是Micrometer的命名规范——Timer追加时间单位后缀,DistributionSummary追加基础单位后缀。如果你在Grafana里按原始名字查询查不到,千万别慌,去/actuator/prometheus看一眼实际暴露的名字再填PromQL。

第二坑:Counter重启归零

Counter依赖内存状态,应用一重启,所有Counter归零,趋势图上会出现"断崖式下跌"。如果你需要跨重启统计总量,应该用sum聚合的同时配合increase函数观察增量,而不是看原始总量。另外,Prometheus本身对Counter的处理也会考虑重启重置场景,rate和increase内部会自动修正。

第三坑:指标基数爆炸

前文说过标签要克制。我有一次给每个请求都打上了userId标签,结果Prometheus采集端开始超时——时间序列数量暴涨,最后不得不推倒这部分埋点重来。标签值必须是有限的、离散的集合,用户ID这种高基数标签绝对不能用。

第四坑:时钟漂移

Prometheus对时间很敏感,如果运行Prometheus的主机和运行Spring Boot应用的主机时间不一致,会导致数据时间戳错位,出现图表延迟甚至"看不到最新数据"。部署时就打个补丁:所有服务器统一用NTP同步时间,这是最基础也最容易被忽略的监控基建。

8.3 一套可复制的完整监控流程

总结下来,我目前在每个Spring Boot服务上落地的监控体系是这样一个闭环:

  1. 接入阶段:引入Actuator和Micrometer,暴露prometheus端点,加上application标签。
  2. 埋点阶段:抽取核心业务场景,定义Counter、Gauge、Timer、Histogram四类指标,落入专门的Metrics服务类。
  3. 采集阶段:Prometheus配置/actuator/prometheus抓取,15秒间隔,规则文件独立管理。
  4. 展示阶段:Grafana建好业务面板,包含速率、耗时分布、积压数值、失败计数等核心图表。
  5. 告警阶段:从业务影响出发写PromQL告警表达式,配合Alertmanager推送到即时通讯工具。
  6. 复盘阶段:每次故障结束后,复盘告警是否在第一时间指出了真实问题,可以反向推动指标和告警优化。

我现在的习惯是:每写一个新的业务接口,顺手把跟它相关的业务指标一并埋好,绝不允许"上线以后再说"。等真出了线上问题再去补监控,那种被迫"盲排"的滋味,体验过一次就够了。这套流程跑通之后,订单链路即使再出问题,我也能在两三个面板之间快速定位到真正的瓶颈,而不是像最开始那样在系统资源指标里瞎转悠。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进