CodeRoad Map 程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。
由 程序员柏风 独立维护 · 关于作者
学习 更多
仪表盘设计 RED/USE 方法;Grafana 思路。
仪表盘设计
这一课你将能做到
用 RED (Rate / Errors / Duration)为判题接口设计最小值班面板集,每个面板回答一个固定问题
用 USE (Utilization / Saturation / Errors)检查 CPU、内存、磁盘、Kafka 队列等资源瓶颈
规划 on-call 看板的分层结构:症状 → SLO → 依赖 → 资源,并留下 drill-down 路径和 runbook 链接
为什么要学
仪表盘若变成「图表墙」——50 个面板堆在一屏,值班时反而找不到「用户是否受伤」。典型翻车:新人收到告警,打开 Grafana 看到满屏绿色曲线,不知道先看哪个,5 分钟后才定位到 RED 面板,止血时间被白白浪费。
好的面板回答固定问题:用户是否痛?痛多久了?可能在哪一层?预算还剩多少? 本课讲设计原则;Grafana 变量、模板、点击操作见 prom-grafana 。本课刻意不克隆那门课的操作步骤,而补齐 观测心智与布局 。面试里「RED 和 USE 的区别」「怎么设计一个值班看板」是高频题。
先建立图像
方法 适用 三要素 判题系统示例 RED 请求驱动服务 Rate(速率)、Errors(错误率)、Duration(延迟分布) 提交接口 QPS、5xx 率、P99 延迟 USE 节点/容器/队列等资源 Utilization(利用率)、Saturation(饱和度)、Errors(资源错误) Pod CPU%、Kafka consumer lag、磁盘 IO 错误
判题 backend 建议的 Grafana 行布局(从上到下):
Row 1 RED — 提交接口 RPS、5xx%、P50/P99(http_server_requests)
用户是否痛?痛多严重?
Row 2 SLO — 30 天可用率、剩余错误预算、burn rate 趋势
承诺还剩多少余量?
Row 3 依赖 — MySQL 连接池、Kafka consumer lag、Redis 命中率
下游是不是瓶颈?
Row 4 JVM — 堆内存、GC 暂停、线程数(解释用,不替代 RED)
应用内部有没有异常?
Row 5 USE — 容器 CPU/内存/磁盘、网络吞吐(容量线索)
资源是不是快满了?
跟着做
步骤 1:为判题接口画 RED 三格(最小值班面板)
纸上三格,每格一个 PromQL:
格 1:Rate(QPS)
sum(rate(http_server_requests_seconds_count{uri="/api/judge/submissions"}[5m]))
回答:现在多少人在提交?
格 2:Errors(5xx 率)
sum(rate(http_server_requests_seconds_count{uri="/api/judge/submissions",status=~"5.."}[5m]))
/
sum(rate(http_server_requests_seconds_count{uri="/api/judge/submissions"}[5m]))
回答:用户在报错吗?错误率多少?
格 3:Duration(P99 延迟)
histogram_quantile(0.99,
sum(rate(http_server_requests_seconds_bucket{uri="/api/judge/submissions"}[5m])) by (le))
回答:最慢的 1% 用户等了多久?
应得到:任何新服务上线前的「最小可值班面板」——三格足够判断「用户是否受伤」。
步骤 2:为判题 worker 补 USE 检查清单
对某个 worker Pod:
Utilization:
- CPU 使用率:container_cpu_usage_seconds_total
- 内存使用率:container_memory_working_set_bytes / limit
Saturation:
- Kafka consumer lag:kafka_consumer_fetch_manager_records_lag
- 线程池队列深度:executor_queued_tasks
Errors:
- 磁盘 IO 错误:node_disk_io_errors_total
- 网卡丢包:node_network_receive_errs_total
步骤 3:设计变量与下钻路径 变量:
$application: 服务名(coderoadmap-backend / judge-worker)
$uri: 接口路径(模板变量,从 http_server_requests_seconds_count 的 uri 标签动态拉取)
$pod: Pod 实例(多副本环境定位单个实例)
总览面板(所有服务 RED 汇总)
→ 点击 coderoadmap-backend → 单服务 RED 面板
→ 点击 /api/judge/submissions → 单接口 RED 面板
→ 面板注释:「P99 突增时,复制 traceId 到 Jaeger 查慢链路」
步骤 4:把告警与面板对齐 JudgeSubmissionHighErrorRate(page 告警)
→ 对应 Row 1 的 Errors 面板
→ 告警注解里直接放面板 URL:https://grafana/d/judge-red?var-uri=/api/judge/submissions
步骤 5:做「删图」练习 候选:HTTP 4xx 率、HTTP 5xx 率、QPS、P50、P95、P99、平均延迟、JVM 堆、
JVM 非堆、GC 次数、GC 暂停、线程数、CPU、内存、磁盘 IO、网络吞吐、
Kafka lag、MySQL 连接池、Redis 命中率、错误预算剩余、burn rate
保留:QPS、5xx 率、P99、错误预算剩余、burn rate、Kafka lag、MySQL 连接池、CPU、内存
删除:P50/P95(P99 已覆盖长尾)、平均延迟(被 P99 替代)、GC 细节(JVM 大盘已含)、
磁盘 IO(低频)、网络吞吐(云厂商监控已有)
删除标准:不能改变故障决策的图优先删 。应得到:少而精的布局,而不是收藏夹式仪表盘。
步骤 6:核对标签与 Spring 侧一致
步骤 7:给判题系统画完整看板结构 Dashboard: coderoadmap-judge-overview(on-call 首页)
Row 1 RED(判题提交接口)
Panel 1: QPS(rate 5m)
Panel 2: 5xx 率(%)
Panel 3: P99 延迟(秒)
Row 2 SLO 与预算
Panel 4: 30 天可用率(当前值 + 趋势线)
Panel 5: 剩余错误预算(时间/次数)
Panel 6: burn rate(1h 和 6h 双窗口)
Row 3 依赖健康
Panel 7: MySQL 连接池(活跃/等待)
Panel 8: Kafka consumer lag
Panel 9: Redis 命中率
Row 4 资源(USE)
Panel 10: Pod CPU/内存使用率
顶部变量:$application, $uri, $pod
底部注释:告警 runbook 链接、Jaeger 查询入口、值班手册链接
讲清楚要点
值班首先关心用户,所以 RED 应置于首页最上方 ——5xx 率上升 10 秒内必须能看到,不需要滚动。
资源问题是因果线索,所以 USE 在下、作解释,不替代 Symptom ——CPU 高不等于用户痛,用户痛了才往下查资源。
单位混乱会误判,所以延迟统一秒或毫秒,比率统一 0-1 或百分比 ——一个面板里 P99 用秒、另一个用毫秒,值班时会算错。
人短时记不住上下文,所以面板注释要链 runbook ——「这个图异常时怎么办」写在面板描述里,不要让 on-call 去翻 Wiki。
SLI/SLO 是承诺,所以预算面板应可见 ——见 obs-slo ;发布前先看预算余量。
不同观众需求不同,on-call 看板 ≠ 容量规划看板 ——值班要实时症状,容量规划要看趋势和资源水位,分两个 dashboard。
下钻靠标签,所以指标基数与命名纪律决定面板能不能做细 ——见 obs-metrics ;标签乱了,变量模板就失效。
你可能会懵的地方
RED 和 USE 能否用在同一个服务?
能。RED 看服务外部表现(用户视角),USE 看它跑在其上的资源(机器视角)。先 RED 后 USE——用户痛了,再往下查是不是资源瓶颈。
只要 Grafana 导入官方 JVM 大盘就够了吗?
JVM 大盘有用,但不能回答「用户 API 是否失败」。JVM 指标是因果线索,不是 Symptom。先 RED,再 JVM。
P99 面板是否要和 Trace 强链?
最好提供跳转说明或示例查询。否则指标告诉你「慢」,你仍不知「哪一跳慢」。在面板描述里写:「P99 突增时,复制 traceId 到 Jaeger 查慢链路:http://jaeger/search?traceID=...」
和 prom-grafana 如何分工?
那课:怎么点 Grafana、怎么配变量、怎么导入 dashboard JSON;本课:面板该回答什么问题、如何分层、如何删繁就简。前者是「怎么操作」,后者是「为什么这么设计」。
多副本环境面板怎么聚合?
按 application 标签 sum 聚合看整体,用 $pod 变量过滤看单实例。不要把 10 个 Pod 画 10 条线——看不出整体趋势。异常时再用变量过滤定位具体实例。
错法对照 错法 问题 正解 50 个面板堆一屏 值班找不到重点,止血时间浪费 分层布局:RED → SLO → 依赖 → 资源 只看 JVM 大盘,不看 RED 资源正常但接口已挂 RED 优先,JVM 作解释 延迟用平均值 长尾被稀释,1% 坏体验被掩盖 P95/P99 + 错误率 面板无注释和链接 on-call 不知道下一步查什么 面板描述含 runbook 和 drill-down 链接 每个 Pod 画一条线 看不出整体趋势,满屏噪音 按 application 聚合,变量过滤单实例 单位混乱(秒/毫秒混用) 值班时算错数量级 全局统一:延迟用秒,比率用百分比
卡点急救
面板变量 $uri 下拉列表为空 :检查指标是否有 uri 标签;确认标签值是模板化的(/api/judge/submissions)而非原始 URL(/api/judge/submissions/12345);在 Prometheus 里手动跑 label_values(http_server_requests_seconds_count, uri) 验证。
P99 曲线出现莫名尖刺 :通常是数据稀疏(低流量时段几个慢请求拉高 P99)。调整方向:增大 rate 窗口(如 [5m] 改 [10m]);或在面板上加 min 样本数 过滤(如 count > 10 才显示)。
面板显示「No data」但 Prometheus 里有指标 :检查 Grafana datasource 配置是否指向正确的 Prometheus;检查面板查询的时间范围是否超出 Prometheus 保留期(默认 15 天);检查标签选择器是否拼错(区分大小写)。
面试常问
RED 和 USE 是什么?区别在哪?
背这个版本:RED 是请求驱动服务的三要素——Rate(QPS)、Errors(错误率)、Duration(延迟分布),回答「用户是否痛」。USE 是资源视角的三要素——Utilization(利用率)、Saturation(饱和度)、Errors(资源错误),回答「资源是不是瓶颈」。值班流程:先 RED 确认症状,再 USE 查资源根因。判题系统例子:5xx 率上升(RED)→ 发现 Kafka consumer lag 满(USE - Saturation)→ 扩容 worker。
怎么设计一个 on-call 看板?
分层结构:Row 1 RED(症状优先,5 秒内看到用户是否受伤)、Row 2 SLO(预算余量,发布决策依据)、Row 3 依赖(MySQL/Kafka/Redis 健康)、Row 4 资源(JVM/CPU/内存,解释用)。每格回答一个固定问题,面板注释含 runbook 链接。变量支持 drill-down:application → uri → pod。核心原则:少而精,删图到 ≤ 10 个。
为什么延迟要看 P99 而不是平均值?
平均值把长尾稀释:100 个请求 95 个 10ms、5 个 10s,平均值约 510ms 看起来还行,但那 5 个用户已经流失。P99 表示「99% 的请求都低于这个值」,反映最差体验。大流量下 1% 就是每天成千上万次坏体验。工程实践:接口延迟看 P95/P99,告警用 P99 + 错误率。
自测三问
判题接口的 RED 三格面板各用什么 PromQL?
为什么 USE 面板放在 RED 下方而不是上方?
设计面板时,「删图」的标准是什么?举例说明两个可以删的候选。
小结一句话 仪表盘不是图表收藏夹——RED 优先、分层布局、每格回答一个问题,值班时 30 秒定位用户是否受伤。
延伸