病毒与故障:漫谈计算机软件的故障应对
原文地址:梁桂钊的博客
欢迎关注公众号:「服务端思维」。一群同频者,一起成长,一起精进,打破认知的局限性。
近期肆虐的新型冠状病毒,已然成为大众视野的焦点。笔者,最近趁过年之际也看了一些相关新闻和书籍,其中,有一本名为卡尔·齐默《病毒星球》让我印象深刻。当然,本文并不是谈及新型冠状病毒和《病毒星球》,而是将故障和病毒进行类比,聊一聊计算机软件的故障应对机制,而其中关于病毒相关科普性的资料和数据来自于《病毒星球》一书。
一、故障:潜伏于计算机软件的病毒
人鼻病毒作为普通感冒和哮喘的罪魁祸首,是人类广泛存在的老朋友。鼻病毒巧妙地利用鼻涕来自我扩散。人擤鼻涕的时候,病毒会借机跑到手上,通过手再蹭到门把手和其他手碰过的地方。下次其他人碰到这些地方,病毒就会借机沾上他们的手,再进入他们的身体——大多数时候也是借道鼻子。鼻病毒能巧妙地让细胞对它们打开一扇“小门”,继而入侵位于鼻腔内部、咽喉内部或肺脏内部的细胞。在接下来的几个小时里,鼻病毒利用宿主细胞,复制自己的遗传物质和包裹它们的蛋白外壳。随后这些复制产生的病毒会从宿主细胞内破壁而出。此外,我们每个人的基因组中携带了近 10 万个内源性逆转录病毒的 DNA 片段,占到人类 DNA 总量的 8%。虽然这类病毒 DNA 中的大多数都没用,但我们的祖先也的确“征用”了一些对我们自身有好处的病毒。如果没有这些病毒,我们甚至没法出生。在演化史上最近的瞬间,人类脱颖而出,病毒对我们的生存功不可没。原本就并没有什么“它们”和“我们”之分——生物在本质上只是一堆不断混合、不断闪转腾挪的 DNA 而已。因此,鼻病毒在几千年前就开始让古埃及人患上感冒,内源性逆转录病毒早在数千万年前就入侵了我们灵长类祖先的基因组。(摘自《病毒星球》)
故障也与之类似,它就好似生命体的 DNA 片段缠绕于计算机软件中,无法割舍。如今软件开发迭代频繁,我们很难全部排除故障,只能说尽可能多地发现和解决问题,避免故障发生在生产环境导致线上问题。当我们遭到病毒感染,细胞释放一种名为“细胞因子”的信号分子,把附近的免疫细胞都召唤过来。它们让我们的身体产生炎性反应,等免疫系统帮我们把体内的病毒全部干掉。而在计算机软件,我们也会有类似的场景,我们的开发人员或测试人员一旦确认是程序 BUG,就会立即记录并周知相关人员进行处理与修复,并持续跟踪,直至故障解决。
二、听过很多案例,依然无法解决故障
感冒这么难治,一个原因是它存在形态多种多样,由于其基于突变及快速复制带来来遗传多样性。而面对故障,虽然它的底层导火索可能就只有哪几种,但是由于技术的复杂性和业务的复杂性导致了计算机软件的整体复杂性。
我们知道 NPE (NullPointerExcepion)会给我们带来巨大灾难,但是我们在实际的研发中经常遗忘或忽视。这里,由于没有对受检对象进行非空判断导致 NPE 故障。
public static void npe03(){ Person person = null; System.out.println(person.blog); }
下面的示例将会导致 NPE,你发现了吗?
public static void npe01(){ Integer x = 1; Integer y = 2; Integer z = null; Integer val = false ? x * y : z; }
而这个示例,也是非常典型的由 Java 自动装箱和拆箱导致的 NPE 故障。
public static void invoke(){ Long x = null; npe02(x); } public static void npe02(long x){ System.out.println(x); }
再聊一个有意思的故障问题。大家都知道由于死循环会导致 CPU 100%。但是,导致 CPU 100% 导因是多样性的,笔者团队曾经遇到一个 JDK 8 的 BUG,它是由于 ConcurrentHashMap 递归创建对象扩展导致死循环,文章链接:https://mp.weixin.qq.com/s/O6UmB7YDKIYtNvqCOjNwDQ。
三、故障应急机制:监控、告警、预案
通常情况下,线上故障一旦发生,其后果一般都比较严重。所以,我们需要尽快解决,降低其带来的影响和资损。例如,我们团队之前口号是:“1-5-10”,即一分钟发现,五分钟处理,十分钟解决。那么,如何做到快速的发现线上故障呢?搭建成熟的监控系统就非常重要啦,例如通过 Zabbix 或 Prometheus 监控各种基础设施(MySQL、Redis、MongoDB、ElasticSearch 等)运行情况,以及业务系统的运行情况,以及 CPU、内存、磁盘 I/O、网络 I/O 等波动情况,还有 GC 情况、binlog 同步情况等等。那么,发现问题后,就需要通过告警系统根据业务规则进行多渠道(邮件、钉钉、电话)联系故障处理人。要快速解决,怎么办?首先,需要一套完备的日志排查系统(日志聚合 + 链路追踪),此外,还需要对于 JVM 相关能快速 dump 堆栈信息,对于自助分析有 DevOps 平台支撑。但是,最主要的还是需要有一套预案体系。什么是预案系统?就是针对不同的问题,有一套完整的预先方案来快速响应。例如,某个服务不可用了,笔者排查发现是由于进程假死了,那么就可以通过预案里面的执行方案执行 shell 脚本进行快速拉活。再比如,笔者通过监控告警感知到某个商家资金异常波动,那么此时通过预案里面的执行方案将其通过动态开关将其快速熔断。
但是,如果这次线上故障没有应急预案,又比较棘手,怎么办?别无他法,只能因着头皮来处理啦。注意的是,故障的评级一般根据业务的影响范围面而定,事实上,最本质的资金损失,包括直接的资损,例如前段时间某知名电商的免额优惠劵导致非常严重的资损;间接的资损,例如挖断电缆导致整个 app 无法使用,那么,转化成正常的交易额也是大把大把的资损呀。然后呢,过了 2 个小时,故障还没修复,可能原先定级 P2 的故障就会升级到 P1。
如果发生最差的情况,就是可能短时间内无法解决,那么就很可能需要停服维修了。例如,近期肆虐的新型冠状病毒导致全国性的封城封路,事实上,也是因为我们没有特效药(计算机软件领域的预案),也还没有研制出新药(计算机软件领域的解决方案),所以只能封城封路(计算机软件领域的停服)。
四、提早发现故障 - 故障演练
通常情况下,偶尔感冒会提供我们的免疫力。而在计算机领域,偶然采取故障演练也可以尽可能确保在线上运行的系统没有缺陷和故障。这里,Netflix 为应对不确定性的领域带来了一种全新的思维模式:混沌工程。事实上,混沌工程提倡我们正面接受系统一定会存在缺陷和故障,然后我们通过一系列实验找出可能发生问题的风险点,进而不断地加固系统。
故障演练可以模拟 CPU 满载、杀掉指定进程、域名访问不通、网络延迟、网络丢包、填充磁盘、磁盘 IO 高等场景,如下所示。
总结一下,故障就像潜伏于计算机软件的病毒,由于技术的复杂性和业务的复杂性导致了其排查和解决的困难性,我们可以采取监控、告警、预案,以及故障演练提早发现故障并解决故障。
最后,欢迎关注我的微信公众号「服务端思维」,里面有更多精彩文章与技术干货。回复”669“获取独家整理的精选资料集,回复”加群“加入全国服务端高端社群「后端圈」,内容过于专业,仅限服务端从业人员。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Serverless 的运行原理与组件架构
本文重点探讨下开发者使用 Serverless 时经常遇到的一些问题,以及如何解决 过去一年,我们和大量 Serverless 用户进行了线上和线下的交流,了解大家的业务场景、对 Serverless 的看法和使用体验。 大部分用户认为 Serverless 会是云计算下一阶段的必然趋势,但不是现在。 为什么呢?因为构成 Serverless 架构的云函数尽管有引以为傲的自动扩缩能力,但是糟糕的开发体验、让人畏惧的冷启动、原有业务的改造难题等等,均降低了使用者的信心。 因此,尽管不少用户认可 Serverless 的价值,但依然认为其很难承载核心业务。 针对这些关键问题,腾讯云在今年 6 月份发布了 Serverless 2.0,全面升级了产品形态、系统调度以及开发者工具。为了便于大家理解,我们就从云函数的运行原理作为切入点,以解释问题产生的原因以及云函数的应对方法。 首先,我们看一下云函数,或者说 FaaS 和 IaaS、PaaS 的区别。 如下图所示,FaaS 不仅给用户提供了标准的 Runtime,同时在应用层也帮用户管理了请求的调度。开发者只需要聚焦在核心业务逻辑开发,按照函数...
- 下一篇
[家乡加油!] 基于 App Bundle 的动态化框架 Qigsaw 1.3.0 重磅推出
作为武汉人,看到家乡遭此疫情,深感痛心,亲人们都在武汉居家隔离中。恳请大家不要用有色眼光对待武汉人、湖北人,武汉加油!中国加油! > Qigsaw 项目地址:https://github.com/iqiyi/Qigsaw 本次 Qigsaw 1.3.0 在家中完成,WFH 体验不错。欢迎大家体验交流,目前已有不少一线厂商接入使用。 本次更新如下: 完成插件延时删除功能。 提供插件依赖自动分析及安装功能。比如插件A依赖B,当插件A被安装,那么插件B会被自动安装。 提供 task qigsawUploadSplit\${variantName}用于插件上传后处理。比如您生成的base apk且所有插件均内置其中,使用qigsawUploadSplit${variantName}可处理base apk中所有内置插件(onDemand属性)上传过程,最后生成新的base apk。需配置qigsawSplit的"oldApk"和"use7z"。 项目地址首页有交流方式,期待大家加入!
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- CentOS8安装Docker,最新的服务器搭配容器使用
- 设置Eclipse缩进为4个空格,增强代码规范