知识卡片
多层异常兜底设计:针对不同故障场景配备不同的补救手段,而非依赖单一机制
内容
QConf针对客户端可能遇到的多种异常场景,没有指望一个万能机制解决所有问题,而是针对每一类具体的失效模式配备了专门的应对手段。针对Agent进程本身异常退出的情况,采用父子进程Keepalive的方式——通过父子进程互相监控存活状态,让异常退出能被及时感知并恢复。针对断网导致共享内存被清空的情况,维护一份落盘数据作为兜底,即使共享内存内容丢失,也能从磁盘上的持久化副本里恢复。针对网络中断后恢复的场景,专门执行一次对共享内存中所有数据的全面检查,并重新注册Watcher——因为网络中断期间可能错过了原本该收到的变更通知,仅仅恢复网络连接本身不足以保证数据是最新的,必须主动做一次全面校验。针对Watcher机制本身可能存在的、不那么容易被直接感知的丢失情况(比如ZooKeeper某些边界场景下通知没有触发),则依靠Scan线程定时(半小时到一小时一次)扫描共享内存与ZooKeeper实际状态做比对,主动发现并修正不一致,作为对前几种”事件驱动”补救机制的最后一道兜底。这四种机制分别针对进程崩溃、网络异常导致缓存丢失、网络恢复后的数据陈旧、通知机制本身可能失效这四种性质完全不同的故障模式,彼此不能互相替代——比如仅靠父子进程Keepalive解决不了网络恢复后数据陈旧的问题,仅靠落盘数据也解决不了Watcher通知丢失的问题。这个案例提示了一条设计高可用系统容错能力的重要原则:真实环境里的异常从来不是单一类型的,指望用一种”通用容错机制”覆盖所有故障场景往往是不现实的,更稳妥的做法是先枚举清楚系统可能遭遇的每一类具体故障模式,再针对每一类分别设计最匹配的应对手段,多层防护叠加起来才能真正撑住生产环境里五花八门的异常情况。
参考来源
- 位置:《高可用架构(第1卷)》第5章《运维保障》"5.1 360如何用QConf搞定两万台以上服务器的配置管理"节,"5.1.5 QConf客户端"及"5.1.8 疑问与解惑"(源文件:_epub-src/OEBPS/Text/Chapter5_1_6.xhtml、Chapter5_1_9.xhtml)
- 结论依据:原文列出"采用父子进程Keepalive的方式以应对Agent进程异常退出的情况。维护一份落盘数据,以应对断网情况下共享内存又被清空的状况。网络中断恢复后,对共享内存中所有数据进行检查,并重新注册Watcher。定时扫描共享内存"四项异常应对措施,并在问答环节补充说明Scan操作"半个小时到一个小时一次",直接支撑本卡片结论。
- 原始内容:采用父子进程Keepalive的方式以应对Agent进程异常退出的情况。维护一份落盘数据,以应对断网情况下共享内存又被清空的状况。网络中断恢复后,对共享内存中所有数据进行检查,并重新注册Watcher。定时扫描共享内存。