资讯详情

老计聊SRE 08:把可靠性写进代码,健康检查与优雅降级

📅 2026/9/14 21:33:17 | 华诺云谱 👁 阅读
老计聊SRE 08:把可靠性写进代码,健康检查与优雅降级
老计聊SRE 08把可靠性写进代码,健康检查与优雅降级本系列的示例应用和脚本开源在 GitHub(仓库地址见文末)。本篇的自愈数据来自对示例应用的真实实验。本篇目标前面几篇,可靠性靠的是人:人去度量 SLI、人去响应告警、人去复盘。但人有反应速度的极限,半夜三点的故障,等人爬起来处理,几分钟就过去了。更高级的思路是:让系统自己扛住一部分故障,不用等人。这一篇讲怎么把可靠性写进代码。学完你将掌握:健康检查是什么,为什么它是自愈的基础超时、重试、熔断、优雅降级这几个把可靠性写进代码的手段用一次真实自愈实验,看进程挂了怎么在1秒内自己回来这种自愈的边界在哪,什么故障它救不了一、健康检查:让系统知道自己还活着一切自愈的起点,是系统能回答一个问题:我现在还好吗。健康检查就是干这个的。通常的做法是给服务开一个专门的端点(比如/health),它返回服务当前是否正常。外部的守护进程、负载均衡器或编排系统,定期来敲这个端点:敲得通、返回正常,说明服务活着,继续给它导流量。敲不通、或返回异常,说明服务出问题了,该采取行动了(重启它、或者把流量从它身上挪走)。健康检查的价值在于:它把服务好不好变成了一个机器能自动判断的信号。有了这个信号,后面的自动重启、自动摘除才成为可能。没有健康检查,系统连自己病了都不知道,更别提自愈。一个小提醒:健康检查要检查真正影响服务能力的东西。比如一个依赖数据库的服务,光返回进程活着不够,最好连数据库连得上也检查了,不然进程活着但数据库断了,健康检查还报正常,就骗了自己。二、把可靠性写进代码的几个手段除了健康检查,还有几个常用手段,让代码自己具备抗故障的能力。超时(timeout):调用一个依赖,不能无限等。设个超时,过了就放弃,别让一个卡住的依赖拖垮整个请求链。没有超时,一个慢依赖能把你的线程全占满,拖死整个服务。重试(retry):有些失败是瞬时的(网络抖一下),重试一次可能就好了。但重试要克制:只对可重试的错误重试、要有次数上限、最好加退避(每次重试间隔拉长),否则故障时一拥而上的重试会变成压垮系统的最后一根稻草。熔断(circuit breaker):如果一个依赖已经连续失败很多次,说明它大概率挂了,这时候继续call它只是浪费时间、拖慢自己。熔断器会跳闸,暂时不再调用它,直接快速失败,过一阵再试探性放一点请求过去看它恢复没。这保护的是你自己,别被一个坏掉的依赖拖下水。优雅降级(graceful degradation):当某个功能实在不可用时,别让整个服务跟着崩,而是提供一个降级的结果。比如推荐服务挂了,就返回一个默认的热门列表,而不是让整个页面打不开。核心思想:坏一部分,总比全崩强。这几个手段的共同点是:故障发生时,不需要人介入,代码自己就做了合理的反应。这就是把可靠性写进代码。超时、重试、熔断、降级,让代码自己扛住故障三、动手:一次真实的自愈实验理论讲完,我们看一次最直观的自愈:进程被杀掉,系统自己把它拉回来。示例应用是用 systemd 托管的,配置了Restartalways(这在第01篇就埋下了)。意思是:只要进程退出了,systemd 立刻把它重新拉起来。这就是最基础的一种健康检查加自愈(systemd 盯着进程活没活,死了就重启)。我们做个实验:后台每 0.2 秒敲一次/health记录成败,然后中途手动把应用进程杀掉,看多久能恢复。真实结果:健康检查采样: 90 次 成功: 86 次 失败: 4 次 进程被杀到首次失败: 0.12 秒 从失败到恢复: 0.86 秒 恢复后 /health: 返回正常进程被杀后不到1秒就被自动拉起,只丢了约4个请求这组数字很能说明问题:进程被杀掉后,0.12 秒就出现了第一个失败请求。但 systemd 几乎同时就发现进程没了,立刻重启,从开始失败到完全恢复,只用了 0.86 秒。90 次健康检查里只有 4 次失败,也就是大约 0.8 秒的窗口里丢了 4 个请求,之后一切恢复正常。这就是 MTTR(平均恢复时间)不到1秒的自愈。整个过程没有任何人介入。换成靠人来处理,光是收到告警、打开电脑、登上服务器,几分钟就没了,而这里 systemd 用不到1秒就搞定了。这说明一个道理:能让系统自己处理的故障,就别留给人。人应该去处理那些真正需要判断的复杂问题,而不是半夜爬起来敲一句重启命令。四、但要清楚这种自愈的边界自愈很爽,但别高估它。上面这个实验有一个明确的边界,必须讲清楚。它只解决了进程级的故障。systemd 的Restartalways能救的,是进程挂了这一种情况。可如果是下面这些呢:整台机器宕机了:systemd 自己都没了,谁来重启?进程还活着,但已经卡死、不再正常响应(假死):systemd 看进程还在,不会重启它。磁盘满了、网络断了、依赖的数据库挂了:重启进程也没用。所以进程级自愈只是第一层。要扛住机器级的故障,需要更高一层的设计:多实例部署:同一个服务跑好几份,分布在不同机器上,挂一个还有别的顶着。健康检查加负载均衡:负载均衡器定期敲每个实例的/health,发现哪个不健康了,就把它从流量里摘出去,别再往坏实例上导流量。这样才能做到:单个实例甚至单台机器挂了,用户几乎无感。我们这次演示的是最基础的进程级自愈,把原理讲透。多实例加负载均衡的健康检查,是同一套思想往上叠一层。进程级自愈是第一层,机器级故障要靠多实例加负载均衡五、小结让系统自己扛故障,比事事等人处理更快更可靠健康检查是自愈的基础,它把服务好不好变成机器可判断的信号;要检查真正影响服务能力的东西超时、重试(要克制)、熔断、优雅降级,是把可靠性写进代码的常用手段,核心是坏一部分总比全崩强真实自愈实验:进程被杀后 systemd 用 0.86 秒自动拉起,只丢约4个请求,MTTR 不到1秒,全程无人介入进程级自愈有边界,救不了机器宕机和假死,那要靠多实例加负载均衡的健康检查下一篇:单个服务扛住了,可流量涨上来怎么办,容量规划,别等雪崩了才想起扩容。参考链接本系列开源仓库(示例应用 自愈实验脚本):https://github.com/Jich1123/sre-aws-labGoogle SRE Book - Handling Overload(过载与降级):https://sre.google/sre-book/handling-overload/Google SRE Book - Addressing Cascading Failures(熔断与重试):https://sre.google/sre-book/addressing-cascading-failures/systemd Restart 配置说明:https://www.freedesktop.org/software/systemd/man/systemd.service.html
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。