欢迎
欢迎
Web 规模的集群包含大量机器。在任意时刻,部分机器运行正常,部分正在启动,部分正在排空流量,部分则已悄然故障。集群之所以能在这种状态下存活,是因为每台机器都能按需回答两个简单的问题:
- /health — 我当前是否能够处理真实请求?
- /version — 我正在运行什么代码?
外加一个指标端点(通常为 /metrics),用于暴露计数器(counters)和仪表值(gauges),供监控工具抓取。
本教程将教你如何设计这些端点,使其真正反映实际状态,解释在代理层中“四大黄金信号”的含义,以及观察到的数据如何驱动容量决策。
学完本教程后,你将能够:
- 设计一个 /health 端点,用于检测真实的路径故障,而不仅仅是进程存活状态
- 设计一个 /version 端点,以便验证部署是否已生效
- 在代理层应用四大黄金信号(延迟、流量、错误、饱和度)
- 将观察到的激增指标与容量决策联系起来:何时扩容、何时排空流量、何时触发告警
- 基于 SLO 和错误预算消耗率进行推理,将其作为“我们该有多在意?”背后的运营准则
两种健康检查
存活检查 vs 就绪检查
存活检查(Liveness):进程是否还活着?由编排器(如 Kubernetes、systemd)使用,以决定是否重启该进程。
就绪检查(Readiness):进程当前是否准备好处理真实流量?由负载均衡器使用,以决定是否向其发送请求。
这是两个不同的问题。一个无法连接数据库的进程是“存活”但“未就绪”的。一个正在启动中的进程是“存活”但“尚未就绪”的。
浅层 vs 深层健康检查
浅层检查:如果 HTTP 处理器能运行,则返回 {"status": "ok"}。非常基础。仅能检测进程宕机。
深层检查:实际执行真实的请求路径。检查数据库连接池能否返回连接、缓存是否可达、下游依赖是否响应。能够检测出浅层检查遗漏的功能性故障。
权衡:深度检查成本更高(每次检查本质上都是一个合成请求),且可能引发级联故障(如果每个副本的健康检查都猛烈冲击数据库,一个缓慢的数据库会使所有副本变为不健康状态,从而将它们从轮询中移除,进而移除所有容量)。
最佳实践:使用浅层检查用于存活状态(快速、低成本、无外部依赖),并使用更深层的检查用于就绪状态(缓存结果,限流以避免猛烈冲击下游服务)。
版本端点
/version 返回 git 提交哈希、构建时间和服务名称。部署后,你执行 curl https://service.example.com/version 并确认返回的提交哈希与你推送的一致。如果不一致,说明部署静默失败了。
如果没有 /version,一个过期的部署可能看起来是成功的,并隐藏数小时。
最小响应结构:{"service": "my-api", "git_commit": "abc1234", "build_time": "2026-05-19T10:00:00Z"}。
延迟、流量、错误、饱和度
四个数字覆盖大部分运维工作
源自《Google SRE 书籍》。在每一个服务层级上测量的四个信号。如果你能很好地对这些信号进行插桩(instrumentation),你就能在用户察觉之前发现大部分生产环境问题。
延迟(Latency):请求需要多长时间?应报告分布情况,而不仅仅是平均值。p99(第 99 百分位延迟)比平均值更重要,因为尾部延迟才是用户感知到的“慢”。一个平均延迟为 50 毫秒但 p99 高达 5,000 毫秒的服务存在真实问题,大多数用户可能从未察觉,但受影响最严重的 1% 用户绝对能感受到。
流量(Traffic):每秒有多少请求?包括总请求数、按端点、按状态码、按区域统计。已知基线;对异常情况进行告警(突然下降 = 入口问题;突然激增 = 流量高峰或攻击)。
错误(Errors):失败请求的比率。区分 4xx(客户端错误,非你的责任)和 5xx(服务器错误,你的责任)。将错误率作为流量百分比来跟踪,而不是绝对计数,以便告警在不同负载水平下都能正常工作。
饱和度(Saturation):系统有多满?CPU 使用率、内存、连接池深度、队列长度。这是领先指标。饱和度会在延迟或错误恶化之前上升。一个处于 90% 饱和度的层级,只需糟糕的一分钟就会面临队列崩溃。
具体到代理层级
每个信号在边缘层都会亮起:
- 代理处的延迟:TLS 握手持续时间、上游连接时间、请求-响应总时间。由于它们位于路径的不同部分,因此分别测量。
- 代理处的流量:每秒总请求数、按后端分布(热门后端表明负载均衡倾斜)、按状态码细分。
- 代理层的错误:来自客户端的 4xx(您的用户访问了错误的端点),来自后端的 5xx(您的服务出现故障),以及代理内部错误(502 = 无法连接后端,504 = 后端超时)。
- 代理层的饱和度:TLS 会话数量、上游连接池深度、代理本身的 CPU 使用率(TLS 终止是 CPU 密集型操作)。
专业提示:如果 502 错误突然增加,但后端延迟很低,这意味着后端在响应之前断开了连接(连接重置、崩溃、内存溢出)。如果 504 错误增加,意味着后端响应缓慢但仍在应答。阅读错误代码;它会告诉您故障发生在哪里。
解读信号
您的仪表板显示过去 10 分钟内的以下情况:
- 流量:大致平稳在 800 req/s(没有激增)
- 延迟:p50 稳定在 40ms,p99 在 5 分钟内从 200ms 攀升至 2,500ms 且仍在上升
- 错误:4xx 比率稳定在 0.3%(正常背景值);5xx 比率从 0.1% 上升至 1.2%(主要为 504 网关超时)
- 饱和度:后端 CPU 在同一 5 分钟内从 45% 上升至 78%;代理 CPU 稳定在 30%
何时扩容,何时排空,何时呼叫人工介入
容量决策需要触发条件
观察指标很容易。知道何时根据指标采取行动,才是其中的纪律所在。
在以下情况下扩容:饱和度持续超过阈值(例如,后端 CPU >70% 持续 5 分钟),或队列深度超过目标值,或 p99 延迟超过 SLO。触发条件应在系统崩溃之前触发,而不是在崩溃时触发。
在以下情况下排空副本:当某个副本持续缓慢或出错,而其他副本运行正常时(单个副本运行过热通常是主机级问题,而非应用问题),或在推出新版本时,或在优雅地退役副本时。
在以下情况下呼叫人工介入:当 SLO 的消耗速度超过错误预算所能承受的范围时,或当饱和度触发条件被触发但自动扩缩容未能吸收该负载时,或当出现级联模式时(错误率和重试率同时上升)。
在以下情况下不要呼叫人工介入:当单个异常分钟自行恢复时,或当后台批处理任务导致预期的周期性波动时,或当噪声超过阈值时(此时是阈值设置错误,而非系统故障)。
SLO 与错误预算消耗
SLO(服务级别目标)定义了可接受的性能标准:“28 天窗口内的成功率 >= 99.9%”。其补集(0.1%)即为错误预算。
消耗速率(Burn rate):指你消耗错误预算的速度。如果你在 1 小时内消耗了 10% 的预算,那么消耗速率是可持续速率的 240 倍(1 小时是 28 天窗口的 1/672;在该窗口内消耗 10% = 10% × 672 = 整个窗口预计消耗 6720%,而允许的最大值为 100%)。
多窗口消耗速率告警:当短窗口(5 分钟,14.4 倍速率)和长窗口(1 小时,6 倍速率)的消耗速率均超过可持续速率时触发页面告警。这能同时捕捉快速故障和缓慢的性能退化。
这对容量的重要性:一个运行在 99.9% SLO 且拥有 1% 余量的服务可以吸收轻微的性能波动。而一个处于 99.93%(勉强达到 SLO)的服务,只需一个糟糕的日子就会违反 SLO。容量决策应针对舒适的 SLO 余量,而非仅仅达到最低标准。
观察下的容量决策
你的服务 SLO 为 28 天内 99.9% 的请求成功。过去一小时的监控当前状态如下:
- 成功率:99.5%(持续 30 分钟)
- 后端 CPU:整个集群平均使用率为 82%(目标值 70%)
- p99 延迟:800 毫秒(SLO 目标:<500 毫秒)
- 流量:1,400 请求/秒,高于基线 1,000 请求/秒(比正常水平高 40%;且趋势仍在上升)
- 自动扩缩容:配置为当 CPU 持续 5 分钟超过 80% 时增加副本;目前正处于扩容过程中,将在约 90 秒内增加 3 个副本
设计一个发布可观测性计划
综合
你现在可以设计一个能捕获真实故障的 /health 端点,一个用于验证部署的 /version 端点,代理层级的四黄金信号仪表盘,以及与 SLO 消耗率绑定的容量触发器。
应用全部四项。
你的团队正在发布 search.example.com(来自故障模式课程中的搜索服务)。团队希望推出可观测性,以便在用户之前发现问题,并配备清晰的“是否告警”决策矩阵。SLO:99.9% 的请求成功,p99 延迟 < 300 毫秒,统计窗口为 28 天。
课程结束
课程结束
你已完成全部五个课程:
- 代理与源站:几乎每个公共 Web 服务都在边缘层使用的架构形态
- 无状态水平扩展:为什么无状态层可以低成本地倍增,以及如何确定其规模
- 入站与出站分离:为什么一台机器会变成两台,以及迫使这种分离的故障模式
- 故障模式与爆炸半径:单点故障(SPOF)、级联故障、事后复盘(Postmortems)、无责行动项
- 可观测性与容量(本课重点):测量什么指标,以便在用户察觉之前让问题浮出水面
核心主线:Web 规模的分布式系统并非魔法。它是一组小规模的模式(反向代理、无状态副本、入站/出站分离、舱壁与熔断器、四大黄金信号)经过深思熟虑的组合。一旦你识别出这些模式,就能在每一个生产级架构中看到它们。
配套课程:五节“几何之*”课程将同样的内容重新表述为图论与几何。无论以何种顺序学习都很合适。
干得漂亮。