又过了1年 618,6月是公司1年1度的大促月,1般提早1个月各系统就会减少需求和功能的开发,转而更多去关注系统可用性、稳定性和管控性等方面的非功能需求。大促前的准备工作1般叫作「备战」,可以把线上运行系统想象成1辆车,大促即是它行将面临的1次严峻驾驶考验。
每次去长途自驾旅行时,我会把车送去对车况做1个全面的检测。汽车工业的历史有1百多年了,而车的构造组成部件又相对固定,已构成了规范且全面的检查事项,我在保养检查手册上看到的检查项目包括:
上面简单列了每个检查大项,而里面又包括1些细节的小项。当技师按这个检查项目列表履行1遍后没有发现问题,就是得出车况良好的结论。但是软件系统的组成部件其实不像汽车那样固定,不同的软件系统可能千差万别,这方面有点像「人」的特性,每一个人是不同的,但又是有共性的,所以医学才能为人建立共同的检测标准,但又需要斟酌差异化并针对个体建立健康档案,这样才能根据检测结果作出相对准确的诊断。
结合这次 618 备战准备,斟酌系统的共性和个性,我想尝试看看能不能抽象出1个针对此类商业在线利用所需的高可用系统保养指南,按此对系统做1个全面地检测后得到对系统运行的1个整体性认识,帮助更好的诊断系统可能潜藏的问题,以便做出及时的优化改进。
我们先从检测开始。
系统利用运行总是需要依托于硬件物理资源,操作系统提供了1些基本的资源使用消耗情况,包括:
操作系统提供的仅仅是单机的资源使用情况,而在1个散布式系统中我们通常需要更高维度的资源使用报告,按集群,按利用等,所以这需要我们自己去做在单机粒度上的聚合和可视化显现。
CPU 除机器整体使用情况,最好能监测到进程级的使用,若1个进程内的 CPU 消耗明显不正常,需要有捕捉到进程内线程 CPU 使用的方法。内存以 Java 利用为例,会更多关心 JVM 内部的内存使用和 GC 情况;而类似 Redis 这样的内存数据库则更多关注其内存的增长趋势。磁盘 I/O 是存储类利用(SQL/NoSQL 数据库)关注的重点,而对大部份服务类利用1般只会打打日志,只关心磁盘存储容量的消耗。网络,站在利用的角度主要关心可靠性(丢包率、延时)、带宽和连接数。
由于利用的情势千差万别,我们先看共性的方面。共有的方面主要包括:
上面属于在利用层能抽象出的共性点,但对具体的业务逻辑则属于个性的地方,这就需要具体问题具体分析。比如,若实现采取了类似像异步内存队列的方式,是不是可以显性化监测?但如果想通过代码巡检来发现这样的个性化场景,投入产出比低,也不太现实。所以,今年 618 我们采取了针对主要业务流程的梳理问答方式,主要用于重新思考代码实现流程,发现1些潜伏逻辑炸弹。所谓逻辑炸弹,就是在正常时1切良好,但遇到某些边界条件可能致使系统性能急剧降落乃至宕机,在今年的备战中确切发现了两枚这样的逻辑炸弹,幸甚。
利用系统运行除依托的环境,还会有对其他利用或数据库、缓存、消息队列等这些基础服务的依赖。每种依赖都需要单独去分析依赖的强弱、可替换性,并提供其可用率、性能等基本监控指标,为诊断提供根据。
强依赖的高可用通常使用主、备方案,而弱依赖除主、备还可以在特定情况下通过消除依赖实现业务降级,这有点像壁虎断尾求生的场景。
前面从资源、利用、依赖3个大类来全面检测评估系统,但检测是需要数据搜集支持的。而以上3类检测项目的数据来源都不1样,在1个大型的散布式环境下就需要将其整合汇总提供面向更高层次的抽象视图。
搜集的方式无外乎两种:
对系统资源和1些使用的开源软件,1般都是 Agent 收集上报到中心服务器,而自研的利用多采取主动上报方式的,最后在中心监控平台上提供抽象视图显现。以下图,1个针对 Redis 集群的数据搜集整合视图,视图最高按集群提供整体数据监视,若有异常可下钻到具体集群中某1台机器上。
监测数据搜集上来后,如何去分析、预警这是1个乍1看简单实际很不简单的事情。
当汽车没油了就会亮1个灯提示你加油,胎压不足了再亮另外1个灯提示你加气,总之汽车的保养手册上画了1大堆唆使灯提示或警示你不同的注意事项,简单直接明了。但我们前面说了软件系统更像1个人,每一年我去医院体检,1共几10项大小检查,总有那末几项指标数字不正常,医生有时也没法简单根据1两项指标异常就可以开出正确的诊断处方。
目前的通用监控预警系统1般只能根据搜集的各类系统指标,设定1个公道范围,若偏离公道范围则发出告警。此类逐一映照式的告警,仅仅完成了最初阶段的任务,提示研发去及时响应。这里面存在的问题就是,当在1个大范围散布式利用系统中,若有1个核心系统出现问题,极可能引发连锁反应,致使告警风暴产生。在这样的风暴中,研发有时也是抓瞎,到处都在喊着火,人人手上都有1个灭火器,却不是知道该往哪里喷。这类情况1方面只能自己做好系统防火隔离带,另外一方面就是增强报警分析诊断。
在应激式报警的基础上,增加分析和诊断逻辑,构成针对利用系统独有的分级诊断式告警。这类告警是1般通用监控预警系统做不了的,而需要利用系统自己在通用数据搜集和告警的基础上来做。惋惜的是这目前还只是1个假想,但方向我感觉是没错的。
预案就是假设某意外事件产生那末我们就履行某个措施,将意外酿成的损失减至最低,迅速恢复系统运行。这是建立在能快速诊断的基础上。前面告警1节说了,若没有针对利用独有的分级诊断式告警,后续的分析、决策是很耗时的,很难到达快速恢复系统的预期目标。
把针对利用平常运营的常见问题归类并做到告警、分析、决策和预案履行程序化后,才有可能真正真正满足 4 个 9 或以上的系统可用性。
…
最后总结下,1份高可用系统的的保养指南包括下面4个方面:
终究要做的就是把这4件事都做成程序化、系统化和自动化的,其中唯1需要人工参与的,我认为只有代码分析1项,这也是程序员的最大价值所在。经历了本次 618 后,我们还才完成了1半多点,只是半自动化,路漫漫其修远兮。
之前忙于业务开发,每到大促都是停下或减缓业务需求来还真实的技术负债,记得好像谁说过这样1句话:
研发水平的体现在于工具的打造和使用。
后面,我想应当需要继续做下去的就是不断打磨工具,让工具可以无人值守的随时为系统做好保驾护航。
写点程序世间的文字,画点生活瞬间的画儿。
微信公众号「瞬息之间」,遇见了无妨就关注看看。
上一篇 仿百度地图街景实现
下一篇 Lua自己实现深度克隆一个值