前面详细介绍了各层涉及的指标:主机层 50 多个 Collector、应用层十来个指标族、接入层 8 个原生指标、依赖层 5 类 Prober。
指标齐了,又产生了新的问题:面板上几百条曲线,告警规则配了四十条,真出事的那一分钟,值班人员还是不知道该先看哪一条。
这不是采集能力的问题,是缺一把挑指标的尺子。
前人早就把尺子做出来了,而且是三把。
- RED(Rate / Errors / Duration)由 Tom Wilkie 提出,把每个服务压缩成三个数;
- USE(Utilization / Saturation / Errors)来自 Brendan Gregg,专门用来描述资源;
- 四个黄金信号(Latency / Traffic / Errors / Saturation)出自 Google SRE,是站在用户视角的四问。
三把尺子说的不是同一件事。
|----------|----------------|---------------------|---------------|
| 对比维度 | RED | USE | 黄金信号(SRE) |
| 提出者 | Tom Wilkie | Brendan Gregg | Google SRE |
| 观察对象 | 请求型服务(API、Web) | 资源型组件(CPU、内存、磁盘、网络) | 面向用户的系统整体 |
| 回答的问题 | 服务好不好用 | 资源够不够用 | 用户感觉到了什么 |
| 三个/四个量 | 速率、错误、耗时 | 利用率、饱和度、错误 | 延迟、流量、错误、饱和度 |
| 短板 | 看不到资源瓶颈 | 看不到业务影响,无请求概念 | 偏宏观,不直接对应单个组件 |
| 本系列对应 | 第4篇、第5篇 | 第3篇 | 第5篇、第6篇 |
三套方法全部落在前几篇已经采集到的指标上,给的是可直接复制的 PromQL、可执行的阈值,以及每条方法各自的适用边界**:不指望把三百条曲线都配上告警,而是把该看的收敛到十条以内**。
注意:RED、USE、黄金信号均为通行方法论,本文的阈值与指标名沿用前几篇已给出的实测值;文中 PSI(Pressure Stall Information)相关指标需额外开启 --collector.pressure,本系列验证环境未启用,已单独标注「未验证」。
一、先把方法选对,再谈配多少告警
1、指标过剩的真实代价
先先一个真实现象:主机层把 CPU、内存、磁盘、网络全配了告警,一共二十多条;应用层又配了十几条。结果一次真实故障是,上游调用超时,应用 http_server_requests_seconds 的耗时曲线抬升,Tomcat 线程池打满;紧接着主机 CPU 反而掉下来了,因为线程都堵在等下游;真正告警响的是「主机 CPU 使用率 < 10%」这类反向规则没配,一条都没响。
问题不在于指标不够,而在于没有区分「因果」和「现象」。CPU 使用率低是现象,线程池饱和才是因果链上的那一环。缺一把尺子,就只能凭经验排查。
2、三把尺子,各自的边界在哪
三套方法不是替换关系,而是分工关系。
- RED 看请求------只要对象在「收请求、返响应」,就问三件事:来量多少、错了多少、慢了多久。应用、Nginx、网关、gRPC 服务全都适用。
- USE 看资源------只要对象是一份「有限资源」,就问三件事:用了多少、排队多深、出错几次。CPU、内存、磁盘、网卡、连接池全都适用。
- 黄金信号看用户 ------换到用户视角问四个问题:卡不卡、量多大、失败没、快满了没。它最大的价值是逼你把延迟拆开看,而不是给新指标。
⚠️ 重点:RED 描述的是服务,USE 描述的是资源,黄金信号描述的是体验。 服务慢了不一定是服务的问题,可能是它下面那块盘在排队,此时 RED 只能告诉你「慢了」,USE 才能告诉你「慢在哪」。
3、选型规则:三个问题定方法
按顺序问以下三个问题定方法:
- 这个对象会不会「收到请求」? 会 → 先上 RED,再补 USE 看支撑它的资源。
- 这个对象是不是一份被共享的有限资源? 是 → 用 USE,别用 RED(磁盘没有 QPS 的概念)。
- 这次排查是从用户投诉开始的吗? 是 → 从黄金信号切入,先定位是延迟、错误还是容量,再往 RED / USE 下钻。
一套监控里,入口用黄金信号、服务用 RED、资源用 USE,三条线各管一段,谁也别越界。越界的结果就是告警互相打脸。
二、RED:面向请求型服务
1、三个指标从哪来
RED 看着简单,落地时最容易出的错是指标选错。三个量在本系列环境里各自对应谁,先对齐:
|------------|--------|-----------------------------------------------------|-----------------------------|--------------------------|
| RED 维度 | 含义 | 应用层(第4篇) | 接入层(第5篇) | 数据来源 |
| Rate | 请求速率 | http_server_requests_seconds_count | nginx_http_requests_total | Micrometer / stub_status |
| Errors | 错误计数 | http_server_requests_seconds_count{status=~"5.."} | OSS 版无状态码指标 | Micrometer / --- |
| Duration | 请求耗时 | http_server_requests_seconds_sum / _count | OSS 版无耗时指标 | Micrometer / --- |
⚠️ 重点:OSS 版 Nginx 给不出 Errors 和 Duration。前面文章已经介绍,stub_status 只有 7 个数字,状态码、upstream 耗时一个都没有。所以 Nginx 这一层只能做半个 RED,真正完整的 RED 要落到网关或应用侧。想在 Nginx 层拿到状态码分布,只有两条路:换商业版 Nginx Plus,或改用 OpenResty 自采。
2、常用 PromQL
# ---------- Rate:QPS ----------
# 总 QPS(按 job + svc 聚合)
sum(rate(http_server_requests_seconds_count[5m])) by (job, svc)
# TOP 10 接口 QPS(定位热点)
topk(10, sum(rate(http_server_requests_seconds_count[5m])) by (job, svc, uri))
# 接入层 QPS
sum(rate(nginx_http_requests_total[5m])) by (job, instance)
# ---------- Errors:错误率(%) ----------
# 5xx 错误率
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) by (job, svc)
/ sum(rate(http_server_requests_seconds_count[5m])) by (job, svc) * 100
# 4xx 错误率(客户端错误,多与上游变更相关)
sum(rate(http_server_requests_seconds_count{status=~"4.."}[5m])) by (job, svc)
/ sum(rate(http_server_requests_seconds_count[5m])) by (job, svc) * 100
# ---------- Duration:平均响应时间(ms) ----------
sum(rate(http_server_requests_seconds_sum[5m])) by (job, svc)
/ sum(rate(http_server_requests_seconds_count[5m])) by (job, svc) * 1000
# 成功请求的平均响应时间,过滤掉异常请求(ms)
sum(rate(http_server_requests_seconds_sum{status=~"2.."}[5m])) by (job, svc)
/ sum(rate(http_server_requests_seconds_count{status=~"2.."}[5m])) by (job, svc) * 1000
# 最大响应时间(长尾,不需要直方图)
http_server_requests_seconds_max
3、验证:三张图一个 Row
RED 的落地验收标准很具体------QPS、错误率、平均响应时间三张图放在 Dashboard 的同一行,时间轴对齐。
对齐之后的好处:三者谁先动一目了然。
- 响应时间先抬、QPS 不变 → 后端慢;
- QPS 先抬、响应时间跟着抬 → 容量不够;
- 错误率先抬、QPS 下降 → 上游已经在熔断。
这个先后顺序,比任何单张图的信息量都大。
4、分析要点与阈值
- 5xx 错误率 > 1% 判定
critical,服务端错误直接影响可用性 - 4xx 错误率 > 5% 判定
warning,多为上游或接口变更 - 平均响应时间 > 500ms 判定
warning,> 1s 判定critical,需按应用特性调整阈值 - QPS 环比波动 > 50% 判定
warning,流量异动(暴涨/暴跌)都要看 - 5xx 告警应配为
critical且for: 5m,避免单次抖动轰炸
5、常见踩坑
注意:
-
rate()窗口不能随手改。 "第5篇 Nginx 监控:流量、连接与性能指标"给过一组平衡值------抓取间隔 15s、rate窗口 5m。窗口用 1m 曲线会抖,用 15m 会把 5 分钟内的流量尖峰整套抹平。RED 的三个量最好用同一个窗口,否则错误率会算出 0~无穷的假象。 -
http_server_requests_seconds默认是 summary,不是 histogram。 Spring Boot 3 / Micrometer 默认只发布_count和_sum,histogram_quantile()直接报空。想要 P95/P99 必须显式配置:management:
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
⚠️ 但是,开直方图会炸指标基数。 每多一个 uri × method × status × le 的组合,序列数就是乘出来的。中小规模应用先只用平均值 + _max,确认需要分位数再开。我在验证环境里就是先开了直方图,Targets 里的 scrape_samples_scraped 能从两位数涨到四位数。
注意:Counter 会归零。 nginx_http_requests_total 在 Nginx 重启后归零,rate() 能自动处理重置,但 Grafana 里若直接画原始值,会出现一个向下的尖峰,别当成异常。
RED 的落地成本极低,只要服务在用 Micrometer,三个量都是白送的。任何新上线的服务,RED 三张图应该和健康检查一起配好,不需要等出故障再补。
三、USE:面向资源型组件
1、三个维度怎么理解
USE 的三个词直译很模糊,落到具体指标上才清楚:
|------------------|------------|------------------------|
| USE 维度 | 一句话定义 | 怎么判断超标 |
| Utilization(利用率) | 资源被占用的时间比例 | 持续高位 = 资源不够 |
| Saturation(饱和度) | 资源排队/积压的程度 | 出现排队 = 已经是瓶颈,利用率还没满也得看 |
| Errors(错误) | 资源本身报错 | 只要非零就要看,不做阈值判断 |
关键区别:利用率高不等于有问题,饱和度才是真信号。
一块盘 io_time 100%,如果队列深度是 1,说明它忙但没堵;io_time 30% 但队列一直在涨,说明上游在疯狂并发提交,问题在别处。
2、CPU
# U:CPU 使用率(%)
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# U:按核心看(定位单核打满)
100 - (avg by(instance, cpu) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# U(虚拟化视角):被宿主机抢走的时间,steal 长期 > 0 说明邻居在抢资源
avg by(instance) (rate(node_cpu_seconds_total{mode="steal"}[5m])) * 100
# S:负载水位(load1 / 逻辑核数,> 1 表示过载)
# 两种写法
sum by(job, svc, instance) (node_load1) / count by(job, svc, instance) (node_cpu_seconds_total{mode="idle"})
node_load1 / on(instance) group_left() count by(instance)(node_cpu_seconds_total{mode="idle"})
# S:阻塞进程数(非零说明有进程卡在 I/O 上)
node_procs_blocked
注意:CPU 没有 Errors 维度。 USE 是一个通用模型,不是所有资源都恰好凑齐三个量,CPU 就是典型的「只有 U 和 S」。别为了凑数硬找个指标填进去,那只会制造噪声。
3、内存
# U:内存使用率(%),用 MemAvailable 而不是 MemFree
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
# S:Swap 使用率(%);SwapTotal = 0 的机器会被 and 过滤,避免除零得到 NaN
((node_memory_SwapTotal_bytes - node_memory_SwapFree_bytes) / node_memory_SwapTotal_bytes * 100)
and (node_memory_SwapTotal_bytes > 0)
# S:内存压力(PSI)
rate(node_pressure_memory_stalled_seconds_total[5m])
# E:OOM Kill 次数(内核 4.13+,vmstat collector 默认开启)
increase(node_vmstat_oom_kill[1h]) > 0
⚠️ 注意:
- 内存的 U 一定要用
MemAvailable,不能用MemFree。 "第3篇 主机层监控实战:node_exporter 核心指标与告警"讲过原因,Linux 会把空闲内存拿去当页缓存,MemFree常年很低是正常现象。用MemFree算使用率,会在每台健康机器上都收到 90% 的告警。 increase(node_vmstat_oom_kill[1h]) > 0该规则需注意:OOM 是「有没有」而不是「有多少」的问题 ,一次 OOM 就意味着一个进程被内核杀过。它不需要for,不需要阈值,只要不为零就该看。
4、磁盘与文件系统
# U:磁盘 I/O 利用率(% 时间在做 I/O)
rate(node_disk_io_time_seconds_total[5m]) * 100
# S:平均读延迟(秒);reads 为 0 时为 NaN,用 > 0 过滤
rate(node_disk_read_time_seconds_total[5m]) / rate(node_disk_reads_completed_total[5m]) > 0
# S:当前在途 I/O 数(瞬时队列深度)
node_disk_io_now
# S:加权 I/O 时间,近似平均队列长度
rate(node_disk_io_time_weighted_seconds_total[5m])
# U:空间使用率(%)
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay|squashfs"}
/ node_filesystem_size_bytes{fstype!~"tmpfs|overlay|squashfs"}) * 100
# U:inode 使用率(%)
(1 - node_filesystem_files_free{fstype!~"tmpfs|overlay|squashfs"}
/ node_filesystem_files{fstype!~"tmpfs|overlay|squashfs"}) * 100
# E:文件系统被内核降级为只读(1 = 只读)
node_filesystem_readonly{fstype!~"tmpfs|overlay|squashfs"} == 1
注意:磁盘的 E 维度,node_exporter 给不出来。 node_exporter 注册的指标只有这些:
node_disk_reads_completed_total node_disk_reads_merged_total
node_disk_read_bytes_total node_disk_read_time_seconds_total
node_disk_writes_completed_total node_disk_writes_merged_total
node_disk_written_bytes_total node_disk_write_time_seconds_total
node_disk_io_now node_disk_io_time_seconds_total
node_disk_io_time_weighted_seconds_total
node_disk_discards_completed_total node_disk_discards_merged_total
node_disk_discarded_sectors_total node_disk_discard_time_seconds_total
node_disk_flush_requests_total node_disk_flush_requests_time_seconds_total
没有 node_disk_read_errors_total ,也没有 node_disk_write_errors_total 。 网上不少指标清单会列出这两个名字,直接抄进告警规则会得到一条永远不触发的空规则,因为底层 /proc/diskstats 本身就不含错误计数。
要拿到设备层的 I/O 错误,现实的取舍是三条:
|--------------------|------------------------------------------|--------------------------------|----------------------------|
| 方案 | 做法 | 优点 | 缺点 |
| 文件系统只读检测 | node_filesystem_readonly == 1 | 零成本,直接反映 ext4/XFS 遇 I/O 错误后的降级 | 事后信号,只能说明已经出事了 |
| textfile collector | 定时 smartctl -a 解析后写入 .prom 文件 | 能拿到 SMART 属性、重分配扇区数 | 需自建脚本与定时任务,维护成本在脚本上 |
| 内核日志 | dmesg / journalctl -k 匹配 I/O error | 信息最全,含设备与扇区 | 不在 Prometheus 体系内,无法参与告警聚合 |
日常监控用方案一兜底,重要数据库所在的物理机再补方案二。不能为了补齐 USE 的第三个字母去造一个假指标。
5、网络
# U:出口带宽利用率(%),1Gbps 网卡按 125 MB/s 折算
rate(node_network_transmit_bytes_total{device!~"lo|veth.*|docker.*"}[5m])
/ 125000000 * 100
# E:接收丢包率(%)
rate(node_network_receive_drop_total{device!~"lo|veth.*|docker.*"}[5m])
/ rate(node_network_receive_packets_total{device!~"lo|veth.*|docker.*"}[5m]) * 100
# E:TCP 重传率(%)
rate(node_netstat_Tcp_RetransSegs[5m]) / rate(node_netstat_Tcp_OutSegs[5m]) * 100
# S:TIME_WAIT 堆积(短连接服务未开 tcp_tw_reuse 时高发)
node_sockstat_TCP_tw
注意: device!~"lo|veth.*|docker.*" 这个过滤不能省。 若不过滤,容器环境下几十个 veth 网卡会把曲线糊成一片,而且它们的流量是重复计算的------同一份流量在 veth 和物理网卡上各算一次。
6、分析要点与阈值
|--------|--------|----------------------|---------------------------------------|
| 资源 | 维度 | 指标 | 阈值 |
| CPU | U | 使用率 | > 70% warning,> 85% critical |
| CPU | S | load1 / 核数 | > 1.5 判定过载 |
| CPU | S | node_procs_blocked | 非零即 I/O 瓶颈信号 |
| 内存 | U | Available 占比 | < 10% 判定 critical |
| 内存 | S | Swap 使用率 | > 80% 且 SwapTotal > 0 判定 warning |
| 内存 | E | OOM Kill | 非零即告警,无阈值 |
| 磁盘 | U | io_time | > 20% warning,> 40% critical |
| 磁盘 | S | 读写延迟 | > 10ms 需关注磁盘健康度 |
| 文件系统 | U | 空间使用率 | > 80% warning,> 90% critical |
| 网络 | U | 带宽利用率 | > 70% warning,> 85% critical(1Gbps) |
| 网络 | E | 丢包率 | > 0.1% 需排查 |
| 网络 | E | TCP 重传率 | > 2% 表明网络质量差 |
USE 的价值不在指标数量,而在「利用率 + 饱和度」这一对组合。单看利用率会误判------一块 90% 忙但零排队的盘,和一块 40% 忙但队列持续在涨的盘,后者才是真出问题的那块。
7、U和S的区别
U(Utilization,利用率)和 S(Saturation,饱和度)看着像近义词,其实回答的是两个不同问题:
- U 回答「忙不忙」
- S 回答「堵不堵」
关键区别在于:U 衡量"占用",S 衡量"等待"。
结合具体指标,再进一步整理U和S的区别:
|--------|-------------------------------------------|--------------------------------------------|
| 资源 | U(占用时间比例) | S(排队/积压程度) |
| CPU | 使用率 node_cpu_seconds_total{mode="idle"} | load1/核数、node_procs_blocked |
| 内存 | MemAvailable 占比 | Swap 使用率、PSI 内存停顿 |
| 磁盘 | node_disk_io_time_seconds_total | 读写延迟、node_disk_io_now、io_time_weighted |
| 网络 | 带宽利用率 | TIME_WAIT 堆积 node_sockstat_TCP_tw |
四、四个黄金信号:从 SRE 到本系列的裁剪
1、四个信号与两套方法的关系
黄金信号不是第四套新体系,它是前两套的「用户视角并集」:
|---------------|-----------------------------|------------------|
| 黄金信号 | 等价于 | 本系列观测点 |
| Latency 延迟 | RED 的 Duration | 接口耗时、拨测耗时 |
| Traffic 流量 | RED 的 Rate | QPS、请求量 |
| Errors 错误 | RED 的 Errors + USE 的 Errors | 5xx 错误率、拨测失败、OOM |
| Saturation 饱和 | USE 的 Saturation | 线程池、连接池、连接水位 |
一句话说清三者关系:黄金信号是「对外可感知的四个面」,RED 是它的服务版缩写,USE 是它的资源版对偶。
2、常用 PromQL
# ---------- Latency 延迟 ----------
# 平均响应时间(ms),未开直方图时的通用解
sum(rate(http_server_requests_seconds_sum[5m])) by (job)
/ sum(rate(http_server_requests_seconds_count[5m])) by (job) * 1000
# P95 成功请求耗时(需开启 percentiles-histogram)
histogram_quantile(0.95,
sum(rate(http_server_requests_seconds_bucket{status=~"2.."}[5m])) by (le, job))
# 拨测侧延迟(第6篇),P95 比平均值更能反映体验
quantile_over_time(0.95, probe_duration_seconds[10m])
# ---------- Traffic 流量 ----------
sum(rate(http_server_requests_seconds_count[5m])) by (job, svc)
sum(rate(nginx_http_requests_total[5m])) by (job, instance)
# ---------- Errors 错误 ----------
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) by (job, svc)
/ sum(rate(http_server_requests_seconds_count[5m])) by (job, svc) * 100
# ---------- Saturation 饱和 ----------
# Tomcat 线程池使用率
tomcat_threads_busy_threads / tomcat_threads_config_max_threads
# 数据库连接池使用率(Druid;HikariCP 换成 hikaricp_connections_* 同理)
druid_connections_active / druid_connections_max
# Nginx 连接水位(512 为 worker_connections 默认值,按实际改)
nginx_connections_active
/ (count(count by (instance) (nginx_connections_active)) * 512)
3、延迟一定要拆开看
黄金信号里最容易被忽略的一条:Google SRE 原始定义中,延迟必须区分「成功请求的延迟」和「失败请求的延迟」。
原因很实在。假设一个接口,正常请求 20ms,一旦出错在 5ms 内返回 500。当故障开始大面积发生时,大量错误请求以 5ms 快速返回,平均响应时间反而下降了。你盯着平均值看,会以为服务变快了。
所以延迟图要按状态码拆:
# 成功请求延迟
sum(rate(http_server_requests_seconds_sum{status=~"2.."}[5m])) by (job)
/ sum(rate(http_server_requests_seconds_count{status=~"2.."}[5m])) by (job) * 1000
# 成功请求的 max,长尾才是体验杀手
http_server_requests_seconds_max{status=~"2.."}
4、饱和信号的两个实战要点
- Tomcat 的 tomcat_threads_busy_threads 高,多半是 I/O 阻塞,不是 CPU 不够。 "第4篇 Spring Boot 应用监控:Micrometer 与 JVM 指标"的告警表里给了这条注释。线程都停在等下游或等数据库,CPU 反而是空闲的------这时候加 CPU 没用,要去看下游的 RED。
- Druid 连接池的
active持续贴近max,说明「连接没被释放」,不是「连接不够」。 优先查慢查询,其次才考虑扩容。第4篇给过阈值:> 80% warning,> 90% critical。
四个信号里,Latency 和 Saturation 最容易被低估。Traffic 和 Errors 是事实,Latency 和 Saturation 是预兆------告警的价值在预兆这一侧。
五、三套方法怎么组合落地
1、分层指标清单
把前六篇的采集结果按方法归一次类,就是一份可以直接照着配的清单:
|-------|---------------------|------------------|---------------------------------------------------------------------------------|---------------------------|----------|
| 层 | 对象 | 主方法 | 核心指标前缀 | 采集组件 | 指标出处 |
| 接入层 | Nginx | 黄金信号(T/E/S) | nginx_http_requests_total、nginx_connections_*、nginx_up | nginx-prometheus-exporter | 第5篇 |
| 接入层 | Spring Boot Gateway | 黄金信号(T/E/S)+ RED | http_server_requests_* | Micrometer + Actuator | 第4篇 |
| 应用层 | Spring Boot | RED + S | http_server_requests_*、tomcat_threads_*、druid_* | Micrometer + Actuator | 第4篇 |
| 运行时 | JVM | USE(内存/GC/线程) | jvm_memory_*、jvm_gc_*、jvm_threads_* | Micrometer | 第4篇 |
| 主机层 | Node | USE | node_cpu_*、node_memory_*、node_disk_*、node_filesystem_*、node_network_* | node_exporter | 第3篇 |
| 依赖层 | 外部 URL / 证书 / 域名 | 可用性 | probe_success、probe_duration_seconds、probe_ssl_earliest_cert_expiry | Blackbox Exporter | 第6篇 |
本表可以直接当作 Dashboard 的骨架:每一行一个 Row,每一列一种方法。行与行之间的下钻路径也是固定的,依赖层失败 → 看应用层 RED;应用层延迟抬升 → 看运行时与主机层 USE。
2、告警收敛:三层 + 抑制
指标清单解决「看什么」,告警收敛解决「响几条」。原则是同一根因只响一条。
- 主机层 :CPU / 内存 / 磁盘 / 网络共 16 条(第3篇表),级别以
warning为主,critical只留给 CPU > 85%、内存 > 90%、磁盘 > 90% 这几条。 - 应用层 :5xx 错误率、平均响应时间、QPS 异动、依赖组件健康共 6 条(第4篇表),5xx 是唯一一条必须
critical的业务类告警。 - 依赖层 :
up、probe_success、成功率、证书到期共若干条(第6篇表),按通用层与 HTTP 层分层。
第6篇已经提过,拨测规则之间存在重叠,要么取舍,要么靠 Alertmanager 抑制。 跨层同样如此,主机整体过载时,不仅主机层规则会响,应用层大概率也会跟着响。
第1篇给的 inhibit_rules 是现成的解法,当时只写了「Critical 抑制同 job+instance 的 Warning」这一条。跨层抑制更实用:
# 统一保留 svc 标签(第2篇约定),即可用 svc 做主键做跨层抑制
inhibit_rules:
# 主机层 critical 触发时,抑制同一 svc 下的应用层 warning
# 主机都趴了,应用层的 warning 是必然结果,不需要重复通知
- source_match:
severity: 'critical'
type: 'node'
target_match:
severity: 'warning'
type: 'jvm'
equal: ['svc']
⚠️ 注意:若file_sd 的 labels 里少写一个 svc,抑制规则就永远不匹配,而规则不匹配是静默失败,不会报错,只会让你在故障时被几十条重复告警淹没。
验证抑制规则是否生效,用官方工具:
$ docker exec -it alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
Checking '/etc/alertmanager/alertmanager.yml' SUCCESS
Found:
- global config
- route
- 1 inhibit rules
- 2 receivers
- 1 templates
SUCCESS
3、常见踩坑
for不能省。 所有 RED / USE 规则都要带for,主机层 5m、应用层 5m、依赖层 1~2m(第6篇给的值)。不带for的规则会把每一次瞬时抖动都变成告警。- 阈值不要静态钉死。 本文给的所有数字都是起点,不是终点,QPS 相关的规则尤其如此,QPS 本身没有绝对阈值,它取决于容量规划。
- 不要为了凑齐框架去造指标。 CPU 没有 Errors、OSS 版 Nginx 没有 Duration、磁盘没有原生错误计数,这些缺口是真实的,如实标注比硬凑一个假规则有用得多。
- 监控体系的完备性,不取决于采集了多少指标,而取决于「采集---展示---告警」是否闭环。本文这套方法,本质上是给这个闭环做减法。
六、小结
指标虽多,但不必面面俱到。三套方法的适用边界很清晰:入口看黄金信号,服务看 RED,资源看 USE。落到具体配置上,一台机器真正需要长期挂着的告警不超过二十条,应用层不超过六条;其余指标按需在专项面板里查,而不是全部转成告警。真正需要看住的,主要是以下几个:
- 5xx 错误率
- 平均响应时间
- 线程池与连接池饱和度
- CPU 与内存使用率
- 以及一次都不该出现的 OOM。
落地建议上,先做减法再做加法:把现有告警规则按 RED / USE / 黄金信号重新归一次类,删掉重复的、补上缺的 E 和 S 维度,再统一 svc 与 type 标签,让跨层抑制能真正生效。标签规范这一步看着琐碎,但它决定了后面所有聚合、抑制、下钻能不能用。
监控不是一次性的配置工作,而是一项需要持续打磨的基础设施。