想象你是“云味楼”餐厅的老板。你站在大堂观察服务员:每小时接多少桌客人(Rate)、多少菜被退回来重做(Error)、客人从点菜到上菜要等多久(Duration)——这是服务视角的“RED 指标”。但你还要走进后厨看设备:烤箱有多少时间在干活(Utilization)、出菜通道排起多长的队(Saturation)、有没有设备时不时罢工(Errors)——这是资源视角的“USE 指标”。服务网格就像你雇的一位全能管家,既帮你在每位员工身上装了记录仪,又把数据汇成墙上一块会报警的仪表盘,让你同时看清“人”的表现和“设备”的状态。这篇文章,我们就从餐厅后厨讲起,手把手搭起这套金指标可观测体系。
金指标把“服务表现”与“资源状态”翻译成统一的数字化语言,是云原生 SRE 面试和实战中绕不开的核心能力。
可视化演示
演示服务网格金指标框架:RED衡请求层、USE衡资源层,结合Sidecar采集与仪表盘,快速定位服务健康与延迟瓶颈。
本节配有交互动效(进入视口后自动加载,约 3KB)。
RED:请求层金指标 Rate速率/Errors错误 Duration延迟 按服务维度聚合,p99对比定位延迟瓶颈
金指标概述
“云味楼”的老板每天要面对两个问题:菜好不好?设备行不行? 前者看服务员的表现,后者看后厨设备的状态。业界把这两类问题抽象成了两组“金指标”:RED 和 USE。RED 看“服务表现”——请求来得多快、错得多不多、等得久不久;USE 看“资源底子”——设备忙不忙、队列堵不堵、坏没坏。两者就像餐厅的两块仪表盘,缺一块都容易误判。
在微服务架构里,服务成百上千,人工盯屏根本不现实。服务网格(如 Istio)恰好充当了那位“全能管家”:它给每个服务实例旁边都安排了一位贴身秘书(Envoy 代理),自动记录每一次请求的进出与耗时,再把数据统一上报。开发者不需要改业务代码,就能拿到全链路的指标数据。
选择金指标有两条硬标准:覆盖核心体验(用户关心的性能与可用性)和可操作性(异常时能指导排查方向)。RED 回答“服务在怎么工作”,USE 回答“资源快不够了没”,两者叠加才能定位“服务变慢是因为代码问题还是资源瓶颈”。这就是金指标在可观测性体系中不可替代的价值——用最少的数据,讲清最关键的真相。
RED指标详解
老板盯服务员就三件事:单量、错单、上菜速度。RED 指标把这三件事变成了三个可量化的数字:Rate(单位时间请求量)、Error(错误请求占比)、Duration(请求耗时分布)。这一组指标专门回答“服务表现如何”,是用户能直接感受到的体验度量。
在 Istio 中,Envoy 代理会自动记录每次请求并生成基础指标,比如 istio_requests_total 带上了来源、目标、响应码、协议等标签。通过一次查询,就能算出三个 RED 数值:用 rate() 函数得到每秒请求量,用响应码不等于 200 的比例得到错误率,用直方图得到耗时分布。这套数据不需要业务埋点,天然对应用透明。
Rate(请求速率) 是流量的“体温计”,公式如下:
Error(错误率) 是可用性的“报警灯”,公式如下:
Duration(耗时) 是体验的“秒表”。平均值容易被极端值拉偏,所以实战中看分位数:p50 代表一半请求的体验,p95 代表绝大多数请求的体验,p99 代表长尾用户的体验。当 p95 明显高于 p50 时,说明存在一批“上菜特别慢”的请求,值得下钻排查。
回到餐厅:光看“一晚上接了 500 单”没用,还得知道 50 单被退、200 桌等了半小时以上,才能真正判断服务好不好。RED 指标的价值正在于此——用三个数字,给“服务表现”画一张不撒谎的快照。
- N_errors窗口内返回 5xx 或业务失败码的请求数。就像被客人退回的菜数量。
- N_requests窗口内请求总数,作为错误率的分母。
- 相除并乘以 100%错误请求在总请求中占的比例,通常以百分数展示。
USE指标详解
如果说 RED 是看“人”,USE 就是看“物”。后厨的烤箱、洗碗机、传菜电梯各有三个关键数:利用率(Utilization)、饱和度(Saturation)、错误(Errors)。烤箱 90% 的时间在烧菜(高利用率)不是问题,但出菜口排队排到走廊(高饱和度)就危险了;设备今天修了三次(Errors 飙升),那再忙也得停下来处理。
利用率(Utilization) 描述资源“有多忙”,公式如下:
饱和度(Saturation) 描述资源“排队挤不挤”,公式如下:
Errors(错误) 在这里指资源层的硬错误:磁盘 IO 失败、网卡丢包、容器 OOM 被杀。这些错误不会直接显示在业务错误率里,却往往是服务抖动的“幕后黑手”。
USE 指标的微妙之处在于:高利用率不一定是坏事——烤箱一直满负荷说明生意好;但高饱和度几乎总是坏事——排队意味着请求在堆积,延迟在恶化。实践时,利用率用于日常容量观察,饱和度用于告警触发,Errors 用于故障定位。三者配合,后厨的“底子”就一览无余了。
- L_queue当前排队等待的任务数。比如传菜通道上堆着的菜品数量。
- C_capacity资源能同时处理的最大任务数。比如传菜电梯一次能放几份菜。
- 相除队列深度与容量的比值,比值接近 1 说明资源濒临极限。
Istio采集配置
要让管家“眼观六路”,第一步是给每位员工装上记录仪。在 Istio 中,这个记录仪就是 Envoy sidecar 代理。你只需给 Kubernetes 命名空间打上注入标签,Pod 创建时 Istio 会自动往里面塞一个 Envoy 容器,与业务容器并肩运行,拦截所有进出流量并默默记录指标。
Envoy 默认在 Pod 的 15090 端口暴露 Prometheus 格式的指标端点 /stats/prometheus。Istio 的 Telemetry v2 机制把这些原始指标加工成 istio_requests_total、istio_request_duration_milliseconds 等高阶指标。如果指标量太大,还可以用 Telemetry 配置做过滤,只保留需要的请求属性,就像管家只记录“谁点了什么菜、等了多久”,不记录每口饭嚼了几下。
指标数量的膨胀速度需要心里有数,公式如下:
采集配置中最关键的一步是:确保 Prometheus 能发现这些端点。Istio 会自动在每个 Pod 上添加注解,声明“我这里有指标可抓”;Prometheus 只需开启注解自动发现即可。等 Pod 启动后,访问 curl localhost:15090/stats/prometheus 就能看到一长串指标,如同打开记录仪的回放:每一个请求的来源、去向、耗时、状态码都清清楚楚。
- M_base单个 Pod 暴露的基础指标数量(Envoy 默认有数百个)。
- n_services / n_pods服务数量与每个服务的副本数量,它们相乘得到总 Pod 数。
- 整体乘积指标总量随服务规模线性放大,这是规划存储容量时必须预判的。
监控系统集成
记录仪装好了,数据得汇入“总账本”才有意义。Prometheus 就是这本账本:它按照设定周期(比如每 15 秒)去每个 Envoy 端口“抄账”,把指标存进自己的时序数据库。之后,无论是画曲线还是写告警,都从这本账本里取数。
Istio 指标的命名遵循 istio_ 前缀 + 名词的规范,例如 istio_requests_total、istio_request_duration_milliseconds、istio_tcp_sent_bytes_total。这些指标自带丰富的标签维度:source_workload(谁发起的)、destination_service(发给谁)、response_code(结果如何)、reporter(由谁上报)。标签是查询的“检索维度”,就像账本里按“日期、窗口、菜品”分类登记。
从原始计数器到可用的 QPS 曲线,需要做一次速率转换,PromQL 写法如下:
集成时还有两个实用技巧:一是用 sum(rate(...)) by (destination_service) 把散落在各 Pod 的指标按目标服务聚合,得到每个服务的总 QPS;二是控制高基数标签——像 source_workload 这样的标签允许很多取值,查询时按需分组即可,但不要把所有标签都塞进告警规则,以免图表卡成演示文稿。
账本齐了之后,监控系统的三个查询范式就成立了:趋势(过去一小时 QPS 怎么走)、对比(两个版本的错误率差多少)、下钻(哪个服务、哪个实例拖慢了整体耗时)。这三大范式将直接支撑后续的告警与仪表盘设计。
- istio_requests_totalEnvoy 维护的累计计数器,只增不减,必须做速率转换才可读。
- [5m]计算时选取最近 5 分钟的时间窗口,窗口越长曲线越平滑。
- rate() 函数计算计数器在窗口内的平均增速,即每秒请求数(QPS)。
告警体系构建
账本记得再全,人不可能 24 小时盯着看,得装上“报警铃”。告警体系的目标是:在用户感知之前,发现异常并通知到人。它不是简单的“错了就喊”,而是一套分级决策机制。
告警规则在 Prometheus 中用一个 YAML 块描述:expr 写触发条件(比如错误率大于 2%),for 写持续时间(比如连续 5 分钟才触发),labels 标严重级别。这个 for 等待期非常关键——它过滤掉瞬时抖动,只对持续恶化的问题报警,避免“狼来了”效应。
设置阈值时,最忌讳拍脑袋。正确的做法是从 SLO 反推:先定业务目标(比如支付服务可用性 99.9%),再反算错误预算(允许的失败比例),最后把告警阈值设在预算消耗过快的位置。公式如下:
告警的最后一公里是通知渠道。Alertmanager(Prometheus 生态的告警分发组件)负责把触发的告警路由给不同的人:P0 级同时发短信、电话、钉钉群,P2 级只发邮件。注意渠道不是越多越好,而是要让“对的人在正确的时间看到关键信息”,否则报警铃响多了,团队会慢慢习惯性忽视。
报警铃装好后,“云味楼”就拥有了自我警觉能力:后厨队列开始拥堵、上菜速度某条线突然变慢,管家都会第一时间通知值班经理,而不是等客人抱怨了才反应过来。
- Error Budget由 SLO 决定的允许错误比例,例如 SLO 为 99.9% 时预算为 0.1%。
- Error Rate当前窗口内实测的错误率。
- 相除并乘以 100%判断预算“烧了多少”,超过 100% 意味着本月 SLO 已无法达成。
仪表盘设计
数据都有了,最后一步是让它们“一眼看懂”。Grafana 仪表盘就是挂在餐厅墙上的那块经营数据板:既是老板的日常驾驶舱,也是故障时的作战地图。设计原则是自上而下分层:顶部放全局健康总览,中部放服务维度对比,底部放细粒度下钻详情。
布局上,第一行放“黄金三件套”:全局 QPS 曲线、错误率曲线、p95/p99 延迟曲线,这是整个系统的心电图。第二行放不同服务的横向对比,用表格柱状图展示哪个服务 QPS 最高、哪个错误最多。第三行放资源 USE 指标,CPU 利用率、队列深度、连接数。这样的金字塔结构让人从宏观到微观,快速锁定问题范围。
Grafana 提供了丰富的视图类型:时间序列图看趋势,状态面板看当前健康度,直方图看延迟分布,热力图看时间段规律。一个实用的视觉技巧是给延迟图叠加 p50/p95/p99 三条线,中间的区域越宽,说明长尾问题越严重。公式如下:
最后一个设计关键是多维筛选联动。Grafana 的模板变量允许在仪表盘顶部加下拉框:选“支付服务”,全页面所有面板立刻联动切换到该服务的数据。按服务、命名空间、版本、实例四个维度下钻,配合 Istio 指标自带的丰富标签,一块仪表盘就能覆盖“全局巡检 → 单服务分析 → 单实例定位”的完整排查链路。
至此,“云味楼”的墙上亮起了一整面数据墙:大堂的服务表现、后厨的设备状态、趋势走向、异常告警,全在掌握之中。老板(SRE)不再需要半夜被电话吵醒后瞎猜,而是打开仪表盘,三分钟之内锁定问题——这就是金指标集成实践的最终价值。
- n窗口内的耗时样本总数。
- 0.95 × n取 95% 的位置索引,向上取整得到目标下标。
- x_下标将所有耗时升序排列后,该下标对应的值即为 p95 耗时。
AI 应用场景
大促流量洪峰预警
阶段:实时监控与预警
解决的问题:电商大促前流量突增,传统人工盯屏发现不及时,扩容决策滞后。通过 USE 指标中的饱和度和 RED 中的速率实时联动,AI 模型可以预测未来 10 分钟的资源占用趋势,提前触发扩容。
具体案例:某电商平台在大促前对订单服务配置了饱和度告警,当队列深度超过容量 70% 且持续 3 分钟时,自动触发扩容流程,同时通过钉钉群通知值班工程师。大促当天服务整体可用性保持在 99.95%。
新版本发布质量门禁
阶段:发布验证与回滚决策
解决的问题:新版本上线后若存在性能回退,靠用户投诉发现太慢。通过对比新旧版本 Pod 的 RED 指标(错误率、p95 延迟),系统可以在发布后 10 分钟内自动判断是否需要回滚。
具体案例:某金融科技公司在每次发布后自动拉取 destination_version 标签分组的新旧版本指标,若新版本 p95 延迟超过旧版本 30% 或错误率超过 0.5%,则触发灰度暂停并通知发布负责人。
故障根因快速定位
阶段:故障诊断与分析
解决的问题:微服务故障定位难,一个服务慢可能牵连整条链路。通过 RED(服务表现)与 USE(资源状态)双视角交叉比对,快速判断是“代码问题”还是“资源瓶颈”。
具体案例:某在线教育平台出现直播卡顿,通过仪表盘发现“互动消息服务”的 p99 延迟飙升,同时该服务所在节点的 CPU 利用率达到 95%、运行队列饱和。结合 USE 指标定位到是资源扩容不足,而非代码问题,扩容后延迟恢复。
Python 演示
#!/usr/bin/env python3# -*- coding: utf-8 -*-"""服务网格 RED/USE 金指标计算演示"""import randomfrom collections import deque class MeshMonitor: """模拟服务网格监控器,计算 RED 与 USE 金指标""" def __init__(self, window_size=600): self.durations = deque(maxlen=window_size) self.total_count = 0 self.error_count = 0 self.busy_ticks = 0 self.total_ticks = 0 self.queue_len = 0 self.queue_capacity = 100 def record_request(self, duration_ms, is_error): """记录一次请求耗时与结果""" self.durations.append(duration_ms) self.total_count += 1 if is_error: self.error_count += 1 def record_resource(self, busy, queue_len): """记录资源利用率与队列深度""" self.total_ticks += 1 if busy: self.busy_ticks += 1 self.queue_len = queue_len def red_metrics(self, window_sec=60): """按窗口计算 Rate / Error / Duration""" rate = self.total_count / window_sec error_rate = self.error_count / self.total_count if self.total_count else 0.0 sorted_dur = sorted(self.durations) n = len(sorted_dur) p95 = sorted_dur[int(n * 0.95)] if n else 0 return { "Rate": round(rate, 2), "ErrorRate": round(error_rate * 100, 2), "p95Duration": p95, } def use_metrics(self): """计算 Utilization / Saturation / Errors""" utilization = self.busy_ticks / self.total_ticks if self.total_ticks else 0.0 saturation = self.queue_len / self.queue_capacity return { "Utilization": round(utilization, 3), "Saturation": round(saturation, 3), } def simulate(): """模拟 600 个请求与资源采样""" monitor = MeshMonitor() for _ in range(600): duration = max(1, random.gauss(45, 10)) is_error = random.random() < 0.05 monitor.record_request(duration, is_error) monitor.record_resource( busy=random.random() < 0.7, queue_len=random.randint(0, 30), ) return monitor def main(): monitor = simulate() red = monitor.red_metrics() use = monitor.use_metrics() print("=== RED 服务视角指标 ===") for key, value in red.items(): print(f"{key}: {value}") print("=== USE 资源视角指标 ===") for key, value in use.items(): print(f"{key}: {value}") if __name__ == "__main__": main()
self.durations = deque(maxlen=window_size)用定长队列做滑动窗口,只保留最近 600 条耗时样本monitor.record_request(duration, is_error)每笔请求记一次账,对应 Envoy 记录请求的过程self.error_count / self.total_count错误数除以总数得到错误率,与 RED 的 Error 定义一致sorted_dur[int(n * 0.95)]耗时升序排序后取 95% 下标,即 p95 延迟self.busy_ticks / self.total_ticks忙碌采样数占总采样数的比例,即资源利用率self.queue_len / self.queue_capacity队列当前长度与容量之比,即饱和度
常见误区
误区服务网格里用了 RED 指标看请求速率和错误率就够了,USE 指标是给基础设施用的,跟我没关系。
正解RED 回答“服务表现如何”,USE 回答“资源还撑得住吗”。服务变慢常常是资源饱和导致的,只看 RED 只能发现“慢了”,看不到“为什么慢”;只看 USE 又无法感知用户体验。两套指标互补,就像餐厅老板既要看服务员上菜快不快,也要看厨房设备有没有趴窝。
为何常见:初学者接触监控时往往从单一仪表盘入手,RED 指标最直观、最容易上手,容易误以为覆盖面够了。
误区看延迟指标时,我看平均响应时间就行,大多数请求都在平均值附近。
正解平均值会被少量极端值拉高或掩盖长尾问题。一个超时 10 秒的请求可以把 100 个 50ms 的请求平均成 148ms,看起来还行,但实际用户体验极差。p50、p95、p99 才能分别反映典型体验、绝大多数体验和最差 5% 的体验。
为何常见:日常看数据天然倾向于“用一个数字概括”,平均值就是在这样的思维惯性下被过度使用了。
误区部署了 Istio,打开 Grafana 就能看到现成的仪表盘和告警,什么都不用配。
正解Istio 只负责采集和暴露指标(Envoy 输出到 15090 端口),后续的 Prometheus 抓取、指标存储、Grafana 数据源与面板、告警规则都需要单独配置。Istio 自带的 Grafana 面板只是一份基础模板,生产环境通常要按业务定制。
为何常见:Istio 的安装向导很顺滑,给人“全自动”的错觉,容易忽略它只是可观测性链路的第一环。
误区USE 指标中的 Errors 和 RED 中的 Error 是一回事,错误率指标可以两边共用。
正解RED 的 Error 统计的是应用层请求失败(如 HTTP 5xx、业务错误码),USE 的 Errors 统计的是资源层硬件或系统错误(如磁盘 IO 错误、网卡丢包、容器被杀)。一条请求可能 5xx,但磁盘没坏;磁盘也可能坏了但请求还没失败。两者来源、含义、排查方向都不同。
为何常见:两个指标都叫 Errors,命名上的相似让初学者误以为语义相同,忽略了它们分属服务层与资源层两个维度。
误区所有服务的告警阈值都设为错误率 1%,超过就报警,简单省事。
正解不同服务对错误的容忍度差异巨大:支付链路可用性要求 99.9%(错误预算 0.1%),日志归档服务即使 5% 错误也不影响核心业务。阈值应基于各自的 SLO 推导,而非拍脑袋统一。否则核心服务在 0.5% 错误率时已经影响收入却不报警,边缘服务 2% 错误却天天误报。
为何常见:统一阈值配置成本低、看起来“标准”,但忽略了业务差异,是缺少 SLO 意识的表现。
面试题
Q1. RED 指标中的 R 表示什么?
- A.Rate 请求速率← 正确答案
- B.Response 响应码
- C.Reroute 流量重路由
- D.Retry 自动重试
答案:A。RED 是 Rate(速率)、Error(错误)、Duration(耗时)三个英文单词的缩写。R 代表 Rate,指单位时间内的请求数量,就像餐厅每小时接待的客人批次。
Q2. USE 指标中的 Utilization 表示什么?
- A.繁忙时间占总时间比例← 正确答案
- B.每秒处理的请求数量
- C.请求中错误的比例
- D.资源发生故障的次数
答案:A。Utilization 指资源被繁忙占用的时间占比,对应公式 U = T_busy / T_total。比如烤箱一天有 70% 时间在工作,利用率就是 70%。
Q3. 下面哪些属于 RED 指标集合?
- A.Rate 请求速率← 正确答案
- B.Error 错误率← 正确答案
- C.Utilization 利用率
- D.Duration 请求耗时← 正确答案
答案:ABD。RED 由 Rate、Error、Duration 三部分组成,对应选项 A、B、D。Utilization 属于 USE 指标集合,它是资源视角的度量,不是服务请求视角的度量。
Q4. 服务网格中负责生成流量指标数据的核心组件是?
- A.Envoy sidecar 代理← 正确答案
- B.Kubernetes API 服务
- C.Grafana 面板服务
- D.Alertmanager 通知器
答案:A。Envoy sidecar 代理以透明代理方式拦截进出 Pod 的流量,并生成 istio_requests_total 等指标。Kubernetes API 负责调度,Grafana 负责展示,Alertmanager 负责告警分发,三者都不是指标生产者。
Q5. p95 Duration 指标的正确含义是?
- A.百分之九十五请求耗时低于该值← 正确答案
- B.百分之九十五请求耗时高于该值
- C.请求在九十五秒后发生失败
- D.每秒处理九十五个成功请求
答案:A。p95 表示将耗时排序后,95% 位置的请求耗时值,即 95% 请求的耗时都低于这个数。它反映了绝大多数用户的延迟体验,比平均值更能暴露长尾问题。
Q6. 一套完整的服务监控告警体系应包含哪些环节?
- A.数据采集与指标存储← 正确答案
- B.告警规则与阈值设定← 正确答案
- C.通知渠道发送告警← 正确答案
- D.前端页面视觉美化
答案:ABC。完整链路是“采集 → 存储 → 查询 → 规则判断 → 通知”。页面美化属于仪表盘设计范畴,与告警体系的告警触发和分发无直接关系。
Q7. RED 与 USE 指标视角的根本区别是?
- A.服务请求视角对比资源状态视角← 正确答案
- B.告警专用对比展示专用
- C.Prometheus 对比 Grafana 工具
- D.全量采集对比抽样采集
答案:A。RED 从服务消费者角度度量“请求表现”,USE 从资源提供者角度度量“资源健康”。两者工具可以相同、采集方式可以相同,但观察的维度和回答的问题截然不同。
Q8. Istio 中 Envoy 代理默认暴露 Prometheus 指标的端口是?
- A.15090← 正确答案
- B.8080
- C.3306
- D.6379
答案:A。Envoy 通过 15090 端口的 /stats/prometheus 路径暴露指标。8080 是常见应用端口,3306 是 MySQL 默认端口,6379 是 Redis 默认端口,都与 Istio 指标采集无关。
Q9. 设计可观测性仪表盘时应遵循哪些原则?
- A.自上而下逐层下钻← 正确答案
- B.一屏聚合核心指标← 正确答案
- C.展示全量原始日志
- D.支持多维度筛选联动← 正确答案
答案:ABD。优秀仪表盘采用“总览 → 详情 → 下钻”的金字塔结构,顶部放核心金指标,详细排查时再下沉。展示全量原始日志会淹没关键信息,适合放到日志系统而非监控仪表盘。
Q10. 滑动窗口计算 Error Rate 相比累计总数计算的优点是?
- A.及时反映最近服务状态← 正确答案
- B.数据总量一定更大
- C.无需存储任何历史数据
- D.计算过程必定更简单
答案:A。滑动窗口只统计最近一段时间(如 5 分钟)的错误率,能及时发现当前恶化;累计总数会把历史正常数据混入,稀释近期异常。好比餐厅看“今天退菜率”比看“开业以来退菜率”更有预警价值。