跳转到内容
123xiao | 无名键客

《Spring Boot 中基于 Actuator + Micrometer + Prometheus 的应用监控体系实战搭建与告警优化》

字数: 0 阅读时长: 1 分钟

Spring Boot 中基于 Actuator + Micrometer + Prometheus 的应用监控体系实战搭建与告警优化

很多团队做完业务功能后,监控往往是“最后再补”。结果一上线就会发现几个典型问题:

  • 服务慢了,但不知道是线程池满了、数据库抖了,还是 GC 频繁;
  • 接口 500 飙升了,但日志太多,根本没法第一时间定位;
  • Prometheus 虽然接上了,但告警全是噪音,不是“报而不警”,就是“警而无用”。

这篇文章我想带你从 Spring Boot Actuator + Micrometer + Prometheus 的组合出发,搭一套能落地的应用监控体系,并重点讲一下 告警怎么做得更靠谱
不是只停留在“把 /actuator/prometheus 暴露出来”这一步,而是把它做成你线上真正敢依赖的一套东西。


背景与问题

在 Spring Boot 体系里,监控能力看起来很容易接入:

  • Actuator:提供健康检查、指标端点、环境信息等;
  • Micrometer:统一指标采集 API,负责把 JVM、HTTP、线程池、自定义业务指标组织起来;
  • Prometheus:负责定时拉取指标,存储时序数据,并支持 PromQL 告警查询。

但现实里常见的问题也非常集中:

1. 只有基础指标,没有业务指标

很多项目接入后只能看到:

  • JVM 内存
  • CPU 使用率
  • HTTP 请求数/耗时
  • 线程池指标

这些当然有用,但真到线上事故时,你会发现它们不够。
比如“下单成功率下降”,如果没有业务指标,你只能从日志里扒。

2. 指标维度失控

Micrometer 支持标签(tag),这很好用,但也很危险。
我见过有人把 userIdorderIdtraceId 这类高基数字段直接塞进 tag,结果 Prometheus 基数爆炸,内存一路飙。

3. 告警过于粗糙

最常见的就是:

  • up == 0 就报警
  • CPU > 80% 就报警
  • 5xx 大于 0 就报警

这种规则最大的问题不是“错”,而是不够贴近真实故障
CPU 80% 不一定有问题,但错误率 3 分钟内连续升高,大概率就是用户正在受影响。


前置知识与环境准备

本文示例环境:

  • JDK 17
  • Spring Boot 3.x
  • Maven 3.9+
  • Prometheus 2.x
  • 可选:Grafana(用于看图,不是本文重点)

我们会实现这些目标:

  1. 暴露 Spring Boot 运行指标;
  2. 增加自定义业务指标;
  3. 用 Prometheus 抓取指标;
  4. 编写更实用的告警规则;
  5. 总结常见坑和优化建议。

核心原理

先把三者关系捋顺,不然后面很容易“会配不会用”。

组件职责

flowchart LR
    A[Spring Boot 应用] --> B[Actuator 端点]
    A --> C[Micrometer 指标注册表]
    C --> B
    D[Prometheus] -->|定时抓取 /actuator/prometheus| B
    D --> E[告警规则 Alert Rules]
    D --> F[Grafana 可视化]

一句话理解

  • Actuator:给应用开“观察窗口”
  • Micrometer:在代码里定义和采集指标
  • Prometheus:来“抄作业”,周期性拉走这些指标

指标的基本模型

Micrometer 常用指标类型:

  • Counter:只增不减,适合统计请求次数、失败次数
  • Gauge:瞬时值,适合队列长度、缓存大小
  • Timer:耗时统计,适合接口延迟、方法执行时间
  • DistributionSummary:分布统计,适合请求体大小、消息大小
  • LongTaskTimer:长任务耗时,适合批处理、导出任务

请求链路中的指标流转

sequenceDiagram
    participant Client as 客户端
    participant App as Spring Boot
    participant Meter as Micrometer
    participant Act as Actuator
    participant Prom as Prometheus

    Client->>App: 发起 HTTP 请求
    App->>Meter: 记录请求次数/耗时/状态码
    Meter->>Act: 暴露为 Prometheus 文本格式
    Prom->>Act: 周期抓取 /actuator/prometheus
    Act-->>Prom: 返回 metrics
    Prom->>Prom: 存储时序数据并评估告警规则

实战代码(可运行)

下面从一个最小可运行例子开始。

1. 创建项目依赖

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>springboot-monitor-demo</artifactId>
    <version>1.0.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.2</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>17</java.version>
    </properties>

    <dependencies>
        <!-- Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Actuator -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- Prometheus Registry -->
        <dependency>
            <groupId>io.micrometer</groupId>
            <artifactId>micrometer-registry-prometheus</artifactId>
        </dependency>

        <!-- 可选:参数校验 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <!-- 测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2. 配置 Actuator 和 Prometheus 端点

src/main/resources/application.yml

server:
  port: 8080

spring:
  application:
    name: order-service

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always
  prometheus:
    metrics:
      export:
        enabled: true
  metrics:
    tags:
      application: ${spring.application.name}
    distribution:
      percentiles-histogram:
        http.server.requests: true
      slo:
        http.server.requests: 100ms,200ms,500ms,1s,2s

这里有两个点值得注意:

  1. prometheus 端点必须暴露,否则 Prometheus 拉不到;
  2. http.server.requests 开启直方图和 SLO bucket,后面我们做延迟告警会用到。

3. 启动类

src/main/java/com/example/demo/MonitorDemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MonitorDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MonitorDemoApplication.class, args);
    }
}

4. 写一个业务接口

我们模拟一个下单接口,并故意制造一些随机慢请求和失败请求。

src/main/java/com/example/demo/controller/OrderController.java

package com.example.demo.controller;

import com.example.demo.service.OrderService;
import jakarta.validation.constraints.Min;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Validated
public class OrderController {

    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }

    @GetMapping("/api/orders/create")
    public String createOrder(@RequestParam(defaultValue = "1") @Min(1) int amount) {
        return orderService.createOrder(amount);
    }
}

src/main/java/com/example/demo/service/OrderService.java

package com.example.demo.service;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class OrderService {

    private final Counter orderSuccessCounter;
    private final Counter orderFailCounter;
    private final Timer orderCreateTimer;
    private final Random random = new Random();

    public OrderService(MeterRegistry meterRegistry) {
        this.orderSuccessCounter = Counter.builder("biz_order_create_total")
                .description("下单请求总数(成功)")
                .tag("service", "order")
                .tag("result", "success")
                .register(meterRegistry);

        this.orderFailCounter = Counter.builder("biz_order_create_total")
                .description("下单请求总数(失败)")
                .tag("service", "order")
                .tag("result", "fail")
                .register(meterRegistry);

        this.orderCreateTimer = Timer.builder("biz_order_create_duration")
                .description("下单耗时")
                .tag("service", "order")
                .publishPercentileHistogram()
                .register(meterRegistry);
    }

    public String createOrder(int amount) {
        return orderCreateTimer.record(() -> {
            simulateLatency();

            if (random.nextInt(10) < 2) {
                orderFailCounter.increment();
                throw new RuntimeException("模拟下单失败");
            }

            orderSuccessCounter.increment();
            return "order created, amount=" + amount;
        });
    }

    private void simulateLatency() {
        int sleepMs = 50 + random.nextInt(1000);
        try {
            TimeUnit.MILLISECONDS.sleep(sleepMs);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

为什么这里同时用了 Counter 和 Timer?

因为这两个维度经常要分开看:

  • Counter 看成功/失败趋势;
  • Timer 看延迟变化。

线上排障时,经常是“错误率没明显升高,但延迟先炸了”。
如果只看一个指标,很容易误判。


5. 增加一个线程池监控示例

很多业务会有异步任务,线程池是事故高发区。
这里我们顺手把线程池指标也挂进去。

src/main/java/com/example/demo/config/ExecutorConfig.java

package com.example.demo.config;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Configuration
public class ExecutorConfig {

    @Bean(destroyMethod = "shutdown")
    public ExecutorService orderExecutor(MeterRegistry meterRegistry) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                4,
                8,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(100)
        );

        ExecutorServiceMetrics.monitor(meterRegistry, executor, "order_executor");
        return executor;
    }
}

这类指标对于判断“服务慢是 CPU 问题还是线程池排队问题”非常有帮助。


6. 运行并验证指标端点

启动项目后,访问:

curl http://localhost:8080/actuator/prometheus

你应该能看到类似输出:

# HELP http_server_requests_seconds  
# TYPE http_server_requests_seconds histogram
http_server_requests_seconds_bucket{application="order-service",error="none",exception="none",method="GET",outcome="SUCCESS",status="200",uri="/api/orders/create",le="0.1",} 3.0

# HELP biz_order_create_total 下单请求总数
# TYPE biz_order_create_total counter
biz_order_create_total{application="order-service",result="success",service="order",} 12.0
biz_order_create_total{application="order-service",result="fail",service="order",} 4.0

然后多请求几次接口:

curl "http://localhost:8080/api/orders/create?amount=10"

如果偶尔返回 500,这是我们故意模拟的,属于正常现象。


7. 配置 Prometheus 抓取

在 Prometheus 的 prometheus.yml 中加入:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'spring-boot-order-service'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['localhost:8080']
        labels:
          app: 'order-service'
          env: 'dev'

启动 Prometheus:

prometheus --config.file=prometheus.yml

打开 Prometheus UI:

http://localhost:9090

你可以先查询这些表达式:

biz_order_create_total
rate(biz_order_create_total{result="fail"}[1m])
rate(http_server_requests_seconds_count[1m])
histogram_quantile(0.95, sum(rate(http_server_requests_seconds_bucket[5m])) by (le, uri))

8. 配置告警规则

这一部分是文章重点。
我建议告警从“用户影响”角度设计,而不是只盯系统资源。

告警文件 alert_rules.yml

groups:
  - name: spring-boot-alerts
    rules:
      - alert: InstanceDown
        expr: up{job="spring-boot-order-service"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "实例不可用"
          description: "{{$labels.instance}} 已经 1 分钟无法抓取"

      - alert: HighHttp5xxRate
        expr: |
          (
            sum(rate(http_server_requests_seconds_count{job="spring-boot-order-service",status=~"5.."}[2m]))
            /
            sum(rate(http_server_requests_seconds_count{job="spring-boot-order-service"}[2m]))
          ) > 0.1
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "HTTP 5xx 错误率过高"
          description: "{{$labels.job}} 在最近 3 分钟错误率超过 10%"

      - alert: P95LatencyTooHigh
        expr: |
          histogram_quantile(
            0.95,
            sum(rate(http_server_requests_seconds_bucket{job="spring-boot-order-service",uri="/api/orders/create"}[5m])) by (le, uri)
          ) > 0.8
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "接口 P95 延迟过高"
          description: "/api/orders/create 最近 5 分钟 P95 延迟大于 800ms"

      - alert: OrderFailureRateTooHigh
        expr: |
          (
            sum(rate(biz_order_create_total{result="fail"}[2m]))
            /
            sum(rate(biz_order_create_total[2m]))
          ) > 0.2
        for: 3m
        labels:
          severity: critical
        annotations:
          summary: "下单失败率过高"
          description: "业务下单失败率连续 3 分钟超过 20%"

      - alert: ExecutorQueuePressure
        expr: executor_queued_tasks{job="spring-boot-order-service",name="order_executor"} > 80
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "线程池队列积压"
          description: "order_executor 队列长度超过 80,可能存在消费能力不足"

然后在 prometheus.yml 中加载规则:

rule_files:
  - "alert_rules.yml"

告警优化:别只会“阈值报警”

我自己踩过最大的坑,就是把告警规则写得太“理想化”。
看起来严谨,实际上要么不报警,要么一片红。

更实用的思路是这几个:

1. 先看比例,再看绝对值

比如 5xx 数量为 10 次不一定严重,但:

  • 总请求只有 20 次,那错误率就是 50%
  • 总请求有 10 万次,那几乎可以忽略

所以业务和接口告警,优先看错误率

2. 一定要加 for

瞬时抖动很常见,尤其是 JVM Full GC、网络抖动、短暂发布切流。
不加 for,很容易一分钟内炸出几十条告警。

3. 延迟告警优先用分位数,不要只看平均值

平均值非常会“骗人”。
99 个请求 10ms,1 个请求 10s,平均值看起来没那么夸张,但用户已经骂起来了。
所以接口延迟更建议看:

  • P95
  • P99

4. 业务指标比系统指标更值钱

CPU、内存、线程数重要,但最终还是要回答一个问题:

用户有没有受影响?

所以优先级我通常这样排:

  1. 业务成功率/失败率
  2. 核心接口延迟
  3. 实例存活
  4. 线程池/连接池/GC
  5. CPU/内存/磁盘

监控体系设计建议

如果你准备在团队里推广这套方案,可以按下面分层建设。

flowchart TD
    A[业务层指标] --> A1[下单成功率]
    A --> A2[支付回调成功率]
    A --> A3[库存扣减耗时]

    B[应用层指标] --> B1[HTTP 请求量]
    B --> B2[HTTP 错误率]
    B --> B3[P95 P99 延迟]
    B --> B4[线程池队列]

    C[运行时指标] --> C1[JVM 内存]
    C --> C2[GC 次数与停顿]
    C --> C3[线程状态]
    C --> C4[类加载]

    D[基础设施层] --> D1[CPU]
    D --> D2[磁盘]
    D --> D3[网络]

    A --> E[告警分级]
    B --> E
    C --> E
    D --> E

这张图表达一个核心观点:
不要把“监控”理解成 JVM 指标采集,而要把它理解成“面向故障定位的观测系统”。


逐步验证清单

如果你想确保整套方案真的可用,建议按下面顺序验证:

第一步:应用自身指标是否正常

检查:

curl http://localhost:8080/actuator/health
curl http://localhost:8080/actuator/prometheus

确认:

  • 端点可访问
  • 能看到 http_server_requests_seconds
  • 能看到自定义的 biz_order_create_total

第二步:Prometheus 是否抓到了数据

在 Prometheus UI 中查询:

up{job="spring-boot-order-service"}

结果应为 1

第三步:业务指标是否随请求变化

连续调用接口:

for i in {1..20}; do curl -s "http://localhost:8080/api/orders/create?amount=10" > /dev/null; done

然后查询:

biz_order_create_total

确认成功和失败计数都有变化。

第四步:延迟直方图是否生效

查询:

http_server_requests_seconds_bucket{uri="/api/orders/create"}

如果没有 bucket 数据,通常是直方图配置没生效。

第五步:告警是否能触发

可以临时把阈值调低,比如把失败率阈值改成 > 0.01,快速制造请求,观察告警状态是否从:

  • inactive
  • pending
  • firing

发生变化。


常见坑与排查

这部分我尽量写得接地气一点,因为这些问题真的非常常见。

1. /actuator/prometheus 返回 404

常见原因

  • 没有引入 micrometer-registry-prometheus
  • management.endpoints.web.exposure.include 没包含 prometheus
  • Spring Boot 版本和 Micrometer 依赖不匹配

排查建议

先看依赖,再看配置,再访问:

curl -I http://localhost:8080/actuator/prometheus

如果是 404,基本就是端点没暴露出来。


2. Prometheus 中 up=0

常见原因

  • 应用地址写错
  • 容器网络不通
  • metrics_path 配错
  • 应用开启了鉴权,但 Prometheus 没带认证

排查建议

从 Prometheus 所在机器直接 curl:

curl http://目标IP:8080/actuator/prometheus

这个动作很朴素,但特别有效。
很多“Prometheus 抓不到”的问题,本质就是网络不通。


3. 自定义指标没有数据

常见原因

  • 指标代码根本没执行到
  • Counter 注册了,但没 increment()
  • Timer 只注册没 record()
  • 指标名写错,PromQL 查询的不是实际名字

排查建议

可以先在 /actuator/prometheus 文本里 grep:

curl -s http://localhost:8080/actuator/prometheus | grep biz_order_create_total

如果这里都没有,就别急着查 Prometheus,先查应用代码。


4. 指标数量爆炸,Prometheus 内存飙升

高危原因

在 tag 里放了高基数字段:

  • userId
  • orderId
  • phone
  • traceId
  • requestId
  • URL 全路径且带动态参数

错误示例

Counter.builder("biz_order_total")
    .tag("userId", userId)
    .register(meterRegistry)
    .increment();

这会非常危险。
Prometheus 擅长处理的是有限维度,不是用户明细表。

正确思路

tag 只保留低基数维度,比如:

  • service
  • endpoint
  • result
  • region
  • tenant(前提是租户数量可控)

5. 延迟指标有数据,但 histogram_quantile 算不出来

常见原因

  • 没开 histogram
  • 查询时聚合维度不对
  • 使用了 summary 却按 histogram 的写法查

排查建议

确认有这类 bucket 指标:

http_server_requests_seconds_bucket

如果没有,检查:

management:
  metrics:
    distribution:
      percentiles-histogram:
        http.server.requests: true

6. 告警反复抖动

常见原因

  • 阈值设得过于敏感
  • for 时间太短
  • 窗口太小,比如只看 [30s]
  • 低流量服务用错误率告警,分母太小导致大起大落

优化建议

对于低流量服务,告警规则最好加一个最小请求量门槛,比如:

(
  sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))
  /
  sum(rate(http_server_requests_seconds_count[5m]))
) > 0.1
and
sum(rate(http_server_requests_seconds_count[5m])) > 1

这样能避免“总共 2 个请求,错了 1 个,错误率 50%”就报警。


安全/性能最佳实践

监控系统不是“开了就行”,它本身也会带来安全和性能成本。

1. 不要把所有 Actuator 端点都暴露到公网

推荐最小暴露原则,只开放必要端点:

  • health
  • info
  • prometheus

envbeansconfigprops 这类端点,生产环境要谨慎,很多信息是敏感的。

更稳妥的做法

  • Actuator 只监听内网网卡或管理端口
  • 通过网关/ServiceMonitor/内网策略限制访问
  • 对敏感端点加认证

例如:

management:
  server:
    port: 9091
  endpoints:
    web:
      exposure:
        include: health,info,prometheus

这样可以把业务端口和管理端口隔离开。


2. 控制标签基数

这是性能优化里最重要的一条。
一句话原则:

标签是为了聚合,不是为了记录明细。

如果你不确定某个 tag 会不会爆炸,先问自己:

  • 它的取值范围是否有限?
  • 未来半年会不会线性增长?
  • 我真的需要按它聚合分析吗?

3. 自定义指标宁少勿滥

不是所有业务动作都要打点。
更推荐抓住“关键路径”:

  • 用户登录
  • 下单
  • 支付
  • 库存扣减
  • 消息消费
  • 外部依赖调用

如果每个方法都打点,除了埋点维护成本高,还会让监控面板信息过载。


4. 为核心接口开启直方图,非核心接口按需开启

直方图很有价值,但也会带来更多时间序列。
生产环境里我建议:

  • 核心接口:开启 histogram,做分位数分析;
  • 非核心接口:保留基础 count/sum 即可;
  • 超高吞吐服务:先评估存储压力。

5. 告警要分级,不要全部 critical

一个比较实用的分级方式:

  • critical:用户明显受影响,需要立即处理
    例:实例全挂、核心链路失败率高
  • warning:性能变差或风险上升,需要关注
    例:P95 延迟升高、线程池积压
  • info:观察类事件
    例:发布后错误率轻微波动

这样值班同学不会一看到告警就麻木。


6. 先做“少而准”的告警集

我建议第一版生产告警先只上这几类:

  1. 实例不可用
  2. 核心接口 5xx 错误率
  3. 核心接口 P95 延迟
  4. 核心业务失败率
  5. 线程池/连接池积压

先把这 5 类做准,比一口气上 30 条规则更有效。


一个更贴近生产的落地思路

如果你要把它推广到实际项目,我建议按这条路径推进:

stateDiagram-v2
    [*] --> 接入基础监控
    接入基础监控 --> 增加业务指标
    增加业务指标 --> 建立核心大盘
    建立核心大盘 --> 定义告警阈值
    定义告警阈值 --> 观察一周
    观察一周 --> 调整噪音告警
    调整噪音告警 --> 固化标准模板
    固化标准模板 --> [*]

这里最容易被忽略的是“观察一周”。
很多团队一上来就把规则写死,结果不是太松,就是太紧。
更稳妥的方式是先观察真实业务波动,再定最终阈值。


总结

回到开头那个问题:
为什么很多团队明明接了监控,线上还是“不知道出了什么事”?

因为他们只完成了“采集指标”,却没有完成“构建监控体系”。

这套方案的核心可以浓缩成几句话:

  • Actuator 负责暴露观测入口;
  • Micrometer 负责统一采集 JVM、HTTP 和业务指标;
  • Prometheus 负责拉取、存储、查询和告警;
  • 真正有价值的,不只是基础资源指标,而是业务成功率 + 核心接口延迟 + 关键资源压力的组合视角。

如果你现在就要落地,我建议按这个最小闭环开始:

  1. 接入 spring-boot-starter-actuatormicrometer-registry-prometheus
  2. 暴露 /actuator/prometheus
  3. 为核心业务加 2 个自定义指标:成功/失败次数、耗时
  4. Prometheus 抓取并先做 3 条告警:
    • 实例不可用
    • 错误率过高
    • P95 延迟过高
  5. 观察一周后再调阈值和分级

最后给一个边界条件:
如果你的服务是低流量、离线型、任务型系统,不要生搬硬套高频 HTTP 服务那套告警策略。
这类场景更适合关注:

  • 任务成功率
  • 任务执行时长
  • 堆积量
  • 最近一次成功时间

监控没有万能模板,只有是否贴合你的系统行为。

如果你把这篇文章里的实战部分先跑起来,再把业务指标补上,基本就已经迈过“有监控”和“能用的监控”之间那道最关键的坎了。


分享到:

上一篇
《Java Web开发实战:基于Spring Boot与JWT实现权限认证、接口防刷与统一异常处理》
下一篇
《前端中级实战:基于 React 与 TypeScript 构建可维护的权限路由与菜单系统》