快的打车|系统坏了,慌不慌

快的打车|系统坏了,慌不慌


\">
我是一个着迷于产品和运营的技术人 , 乐于跨界的终身学习者 。 欢迎关注我哟~
每周五12点 按时送达~
我的第「151」篇原创敬上
大家好 , 我是Z哥 。
作为程序员 , 相信有一件事是大家最不想见到的 。 那就是 , 线上运行的系统出现了技术性故障 。 (特别还是周末你正在外面happy的时候:D)
处理这类事情特别能体现一个人的综合能力 。 因为它会涉及到抗压能力、对外的沟通能力 , 以及排查问题所需的技术能力等等多个方面 。
【快的打车|系统坏了,慌不慌】如果你还没机会成为核心开发 , 其实很少会有这样充满压力的经历 。 因为在这个情况下处理事情其实是很慌的 , 毕竟所有使用系统的人以及他们的老板、你的上级、你的老板等等无数双眼睛都在盯着这件事情 。
我还记得有一年双11 , 我作为“首席问题处理官”正在紧急处理服务器扛不住压力的问题 , 老板默默走到我身后问到“什么问题啊?什么时候好?” 。 你脑补一下这画面 , 想象一下看看 。
只要你接下去还会继续从事程序员这个职业 , 我想这样的场景你总归会有机会遇到的 。 因为一个著名的定律——墨菲定律 。

墨菲定律:凡是可能出错的事就一定会出错 。
如果没有一个清晰的应对思路 , 那么一旦发生线上问题就会像热锅上的蚂蚁一样 , 急得团团转 , 像无头苍蝇一样到处乱撞(试) 。
所以 , 我这次就想分享一些我多年作为“首席问题处理官”所总结下来的经验 。 这可是承载了我N多汗水和脑细胞的经验~
在日常的项目开发迭代过程中我们遇到一个bug , 大家的处理过程几乎是一样的:定位bug -> 解决bug 。 可能少部分人在解决bug之后会有一个思考、复盘 , 看看是否有类似bug的地方 , 一并处理掉 。
这个“定位 -> 解决 -> 复盘”的过程也同样适用于线上问题的处理 。 但是必然不仅仅如此 。
俗话说 , 解决一个问题最难的地方不是解决的过程 , 而是定位的过程 。 所以 , 针对线上问题我们等不起定位问题所花费的时间 , 因此要将「恢复」系统正常使用放在最首要的位置 。 所以 , 这个过程就变成了:“恢复 -> 定位 -> 解决 -> 复盘” 。
这里多说一句 , 有一部分人的观点认为 , 将恢复系统作为首要目标 , 应当包括牺牲保留现场的动作 , 因为这个动作可能也需要耗费数分钟才行 。
我对这个观点持反对意见 。 理由是 , 解决问题的时长的确是一个很重要的指标 , 但是问题既然已经发生 , 如果由于没有保留现场导致后续没有排查到根源 , 导致下次该问题再次出现 , 到时候场面将会更加难看 。 所以我对这事的观点是 , 保留现场最重要 。 因此 , 这个过程又变成了:“保留现场 -> 恢复 -> 定位 -> 解决 -> 复盘” 。
当然了 , 保留现场也不是说非得面面俱到 , 花很多时间 。 用最快的方式保留你当下所能想到的所有相关线索的地方即可 。 如果事后还是由于线索不足导致未能排查到根本原因 , 那只能说经验不足 , 考虑一下以后需要多保留哪些现场数据才行 。
好了 , 确定了这5个步骤 , 那么具体每个步骤可以做些什么呢?我来一个个说 。
/01 保留现场/保留现场最最最重要的一件事是保存异常程序的dump文件 。 有了它 , 你就可以摆脱盲人摸象式的分析问题 , 可以快速定位问题的发源地 。
我用了三个“最”来强调它的重要性 。 如果你还没掌握它 , 那么后面我提到的东西都先放一放 , 先去掌握它 。
另外 , 如果系统的监控体系并不完备的话 , 还需要将问题发生时 , 操作系统、各第三方组件自带的监控数据快速地通过截图保存下来 。
保存监控数据的时候要特别留意一下网络相关的数据 。 如果发现网络相关的数据有异常 , 那么再把当下的网络连接情况通过命令保存下来 。 因为相对来说 , 网络出现问题的概率远远大于硬件 , 不管是程序导致的还是其他原因 。 规模越大的系统 , 越是如此 。
/02 恢复/恢复系统访问有很多方法 。 首先不得不提到一个适用于80%情况的神技了——重启 。 没错 , 根据多年的经验来看这招的确在大多数情况下很有效 。
也正因为屡试不爽 , 所以很多人习惯性地会在第一时间去重启 , 导致现场忘记保存并受到破坏 。
重启也分两种 , 强制重启和自然重启 。 当然优先考虑自然重启 , 这样能避免产生一些意料之外的脏数据 。 但是如果是系统出现资源耗用异常的话 , 就不要傻傻地等自然重启了 , 只能强制重启(kill掉进程) 。
第二种常见的方法是「回滚」 。 当然它的前提条件是你判断下来问题的出现是由于最近一次发布 。 否则盲目的回滚不但起不到作用 , 还会越弄越乱 , 特别在分布式系统中 。 因为在分布式系统中 , 一旦上下游耦合的地方出现对接不上 , 轻则报错 , 重则出现大量的异常数据 , 够你后续折腾好久的 。
第三种方法是「降级」 。 暂停出问题的模块 , 停止服务 。 当然 , 这个动作需要和业务方做好沟通 , 是否单独降级某个模块会导致业务不完整之类的问题 。
第四种方法是「限流」或者「扩容」 。 如果你发现是系统扛不住突增的流量 , 如果有条件的话可以快速扩容几台机器和程序 。 如果没法扩容的话可以选择限流 , 将一定百分比的请求直接拒绝服务 。 毕竟所有无法提供服务和部分无法提供服务相比 , 肯定还是后者划算 。
还有一些比较小众的方法是「切到备机」、「故障隔离」等 , 这里就不展开了 。 它们对环境、条件的要求更多一些 。
有时候可能系统并未恢复到完全正常的状态 , 比如 , 读取数据是OK了 , 但是某些操作写入数据到时候还是有问题 。 在这样的情况下 , 不要着急定位问题 , 还是先尽最大努力恢复到最大程度的可用状态再进行下一步的动作 , 毕竟用户第一嘛 。
/03 定位/关于定位问题 , 如果有dump文件的话最方便了 , 通过dump文件分析工具来分析dump文件就可以快速定位到出问题的代码行 , 特别是程序阻塞、内存溢出、cpu100%之类明显是程序本身的问题 。
不同的语言有不同的dump分析工具 , 可以自行网上搜一下教程 。 最终目的就是定位到异常点的堆栈信息 , 有了它就相当于直接把问题代码出现在哪里都给定位到了 。
如果说分析dump文件是跳过抽丝剥茧的步骤 , 直击要害的话 。 通过监控数据、日志层层分析是个慢活 。 但是如果缺失dump文件或者从dump文件从未能分析出问题的情况下 , 也只能选择后者 。
我们在看日志、监控数据的时候一定要有关联起来看的意识 , 而不能仅仅在单个维度上看 。 因为有时候你在单个维度上看到的数据像是正常的 , 但是你关联起来看就不一定了 。 比如 , tcp连接数降低了一半 , 但是内存反而涨了100% , 为什么?这里面可能就藏着故障的线索 。
/04 解决/定位到了问题 , 解决起来就很简单了 。 该改代码的改代码 , 该改配置的改配置文件 。 这里就不多说了 , 毕竟情况太多 , 大家遇到的可能都不太一样 。
/05 复盘/大家都知道复盘的好处 , 但是真正做复盘的人真不多 。 如果你不知道从何下手来做复盘的话 , 不妨从以下几个问题入手 ,
  • 这次故障原因是什么?
  • 是否有更快的方式在当时来恢复业务?
  • 如何避免再出类似故障?
  • 当前系统中是否还有类似的潜在风险?
如果你能回答这些问题 , 我觉得这个复盘就很到位了 , 剩下的就是执行 。
当然了 , 不管如何优秀的处理故障 , 最理想的还是不要发生故障 。 所以我们需要在前期做更多的准备 。
/01 了解你的程序/我们很多人了解自己负责的程序只有通过coding这一种途径 。 除非该程序是个单体应用 , 否则这样的方式是远远不够的 。
我建议你按照以下清单去了解你的程序:
  • 程序包含有哪些模块 , 对应使用者是哪些?哪些是核心模块 , 哪些是可以“弃车保帅”的?
  • 多个模块/系统
    如何流转的?(尽量画一个流程图 , 加深记忆)
  • 依赖了哪些中间件 , 谁负责维护他们?
  • 依赖了哪些其他的程序 , 强依赖还是弱依赖 , 谁负责维护他们?
  • 依赖的存储、消息队列背后又依赖了哪些存储 , 存储运维负责人是谁?
  • 线上的程序部署在什么环境 。 你是否有条件独立进行部署并调优?
/02 做好监控/大多数的故障不是突然发生 , 而是有一个逐渐积累的过程 , 直到爆发 。 所以监控的价值不仅仅是看看数据那么简单 , 对于异常识别特别有帮助 。
一般监控分两个维度 , 系统维度和业务维度 。 监控指标分为三层 , 「环境指标」、「程序指标」、「业务指标」 。 具体怎么做我在之前的文章《分布式系统关注点——360°的全方位监控》有具体说明 , 这里就不赘述了 。
如果是分布式系统 , 还可以搭建一个请求链路跟踪系统 。 有很多成熟的现成解决方案 , CAT、SkyWalking、Zipkin、Pinpoint等等 。
多说一句 , 我们在做监控预警的时候 , 除了设置阈值还要关注一下波动率 。 比如 , 某项资源日常使用率20% , 除了设置超过80%的阈值进行预警之外 , 在它产生波动幅度100%(使用率40%)以上的时候也需要预警 , 提前让人关注 。 否则一旦以一个较快的速度增长到80%之后 , 留给你在故障爆发前消灭它的机会就非常渺茫了 。
另外 , 针对常见的故障预设几套故障响应方案 , 以及进行定期的故障演练(一般上了一定规模的公司或者处于扩张期的公司才会考虑)可以让团队面对线上故障的时候更加地游刃有余 。
假如你不幸成为了线上故障的解决者 , 如果上级不在旁边的话 , 需要定时向上级汇报问题处理情况 , 以便TA了解问题的严重程度、修复进度并作出决策 。
反正就算你不上报 , 迟早也会被催 。 与其被动的被催 , 不如主动上报 。
好了 , 总结一下 。
这篇呢Z哥和你分享了一些处理线上故障的经验 。
从思路上 , 分为五个步骤“保留现场 -> 恢复 -> 定位 -> 解决 -> 复盘” 。 除了第四步「解决」外 , 我都进行了展开 。
  1. 保留现场 。 主要是保存dump文件 , 以及截图系统监控的数据(没有在外部搭建的监控系统内的部分) 。
  2. 恢复 。 主要重启、回滚、降级、限流和扩容 。 还有一些小众的方法「切到备机」、「故障隔离」等
  3. 定位 。 分析dump文件、分析监控数据、程序运行日志 。
  4. 解决 。
  5. 复盘 。 搞清楚以下4个问题就够了:
  • 这次故障原因是什么?
  • 是否有更快的方式在当时来恢复业务?
  • 如何避免再出类似故障?
  • 当前系统中是否还有类似的潜在风险?
然后还建议了你要未雨绸缪 , 尽可能减少故障在线上爆发 。
  1. 解你的程序
  2. 做好监控
希望对你有所帮助 。 这篇纯干货 , 建议收藏一下 , 顺手可以再点个赞哦 。
推荐阅读:
  • 平台or职位 , 你怎么选?
  • 如何优雅做系统错误提示?
也可以「关注」我 , 带你以技术思维看世界~内容包括:架构设计丨分布式系统丨产品丨运营丨个人深度思考 。


    推荐阅读