智汇 IT
城启新篇

高可用架构的故障域设计别让一次机架掉电带走整条链路

凌晨两点十七分,手机开始震。我眯着眼看了一眼,P0告警,核心交易接口的P99延迟直接从80毫秒飙到了4秒。爬起来打开电脑,日志里一片红。查了二十分钟,原因有点黑色幽默——某个机架的TOR交换机重启了。就那么一个机架。可那个机架上跑着这个服务60%的实例。剩下的40%在另一个机架?不对,也在同一个可用区,共享同一台上联交换机。说白了,整个服务就是一颗鸡蛋,只不过放在了一个篮子的不同角落里。

这事儿吧,真不怪运维。要怪就怪当初画架构图的时候,没人认真问一句:故障域到底怎么划?

故障域不是你画的那个圈

很多人一听“故障域”,第一反应就是“多机房”。双活、异地多活,词儿一套一套的。但你问他:机房里的机架算不算故障域?同一台物理机上的两个虚拟机算不算?他愣一下,说这得看情况。

对,就看情况。故障域的本质是一个边界。在这个边界里面,一个故障会同时干掉所有东西。边界外面,故障被隔离。机房是一个故障域。机架是。可用区是。甚至同一个交换机下的所有机器都是。你做了多副本,三副本,听起来挺安全。但如果三个副本全在同一个机架,那机架掉电的时候,三个副本一起没。这不叫高可用,这叫复制粘贴。

说实话,我见过最离谱的一个案例:某业务做了跨机房部署,主库在A机房,从库在B机房。听着没问题吧?但是——从库的VIP和主库的VIP在同一个网段。机房A的网关一挂,B机房的从库也失联了。故障域没隔离干净,跨了个寂寞。

数据中心机架级故障域隔离拓扑示意图
数据中心机架级故障域隔离拓扑示意图

故障传播比故障本身更可怕

单点故障顶多是某个功能不可用。但故障传播不一样,它会像病毒一样顺着调用链爬。

举个例子。服务A调用服务B,B调用C。C在另一个可用区,平时延迟5毫秒。突然有一天,C所在的可用区网络抖动,延迟变成500毫秒。B调用C的连接池瞬间被打满。B的线程池开始排队。A调用B的超时时间设的是1秒,1秒内没返回,A开始重试。重试放大了流量,B的线程池彻底爆了。然后A也挂了。一个可用区的网络抖动,最后把整个链路都带走了。

这事儿怪谁?怪网络抖动?怪C?都不是。怪故障域之间的耦合太紧。你虽然把服务部署在了不同的可用区,但同步调用链把它们又绑在了一起。物理上隔离了,逻辑上没有。

怎么破?三件事。超时。熔断。异步化。超时时间要设得合理,别搞个30秒,那跟没设一样。熔断要能自动恢复,别一熔断就再也不打开了。异步化最彻底,但改造成本高,得看业务能不能接受最终一致性。我的观点是:如果一个调用链上的服务,有一个挂了不影响主流程,那就把它改成异步。别为了那点实时性,把整个系统搭进去。

微服务同步调用链故障传播与熔断降级示意图
微服务同步调用链故障传播与熔断降级示意图

几个能落地的笨办法

几个能落地的笨办法
几个能落地的笨办法

先说一个反直觉的:容量规划要按故障域来算,不是按整体来算。你做了双机房,每个机房平时跑50%的流量。看起来能互相兜底。但问题是,当一个机房挂了,另一个机房能瞬间扛住100%吗?缓存预热了吗?连接池够大吗?线程池不会排队排到天荒地老吗?我见过太多系统,平时跑得好好的,一切换就雪崩。原因特别朴素——剩下的那个机房,从来没按100%的压力测试过。

所以笨办法之一:定期做故障演练。别光画架构图。每个月挑一个机架,把上面的实例全下线。看看系统怎么反应。Chaos Engineering听着高大上,其实一个脚本就能干。随机kill掉一批实例,观察五分钟。你会发现很多你以为设计了但其实没生效的东西。比如某个服务的重试策略,比如DNS缓存,比如连接池的回收逻辑。

笨办法之二:把故障域层级写进发布规范里。同一个服务的实例,不允许全部调度到同一个机架。这事儿靠人记不住,得靠调度器强制。Kubernetes有topologySpreadConstraints,用起来。别嫌麻烦。你嫌麻烦,故障就来找你麻烦。

笨办法之三:故障域要跟着业务变。去年你的服务只有三个实例,放在两个机架里就够了。今年业务涨了十倍,实例变成三十个。如果还是只放在两个机架里,那单个机架的故障影响面就从50%变成了50%——看起来没变,但绝对数量从1.5个实例变成了15个实例。故障域的设计不是一次性的。业务在变,架构在变,故障域也得跟着重新评估。

最后说句实在的。高可用架构的故障域设计,核心不是追求“永不宕机”。那玩意儿不存在。核心是控制爆炸半径。一个机架挂了,影响20%的用户,能接受。影响80%,不能接受。就这么简单。别把系统设计成一颗完美的鸡蛋。把它设计成很多颗小鸡蛋,放在不同的篮子里。这样你凌晨两点才能睡得着。

对了,那个交换机重启的故障,最后怎么解决的?我们把实例重新做了反亲和性调度,强制分散到三个机架。然后加了个机架级别的熔断开关。再后来,那个机架又抖了一次。这次P99只从80毫秒涨到了120毫秒。短信没响。我睡了个整觉。

免责声明:市场有风险,选择需谨慎!此文仅供参考,不作买卖依据。如有侵权请联系删除。
文章名称:高可用架构的故障域设计别让一次机架掉电带走整条链路
文章链接:https://m.itcdj.com/news/848.html