比如我之前分享的《谷歌可靠性工程的设计经验》和《谷歌Colossus文件系统的设计经验》都是在思考区块链存储如何借鉴谷歌的经验。
最近参与了Filecoin太空竞赛的部分工作,对整个网络的复杂性有了新的认识和思考。整个网络在300个小时左右的时间内封装了100PB的数据,对于一个测试网络来说,这是一个了不起的成绩。
但应该注意到的是,依然有大量矿工没有能力参与,并且部分参与的矿工也都出现了掉算力的情况,甚至是部分矿工集群整体故障,退出网络。
前一篇文章已经谈过,运维能力是Filecoin挖矿的战略能力。近日又恰好读到一篇谷歌的文章《Debugging Incidents in Google's Distributed Systems》,介绍了谷歌如何端到端的调试复杂分布式系统中的故障。
那么,本文就基于目前工作中的体会,分享一下从谷歌的调试经验中可以获得的实用策略。
一、谷歌面临的挑战是业内少有的
网络上流传的一个关于谷歌在DevOps领域,以及在自动化测试领域所面临的挑战:
1.5万程序员(包括开发与运维);
4000个同时进行的项目;
在同一个库里 check 所有的源代码(数十亿文件!);
5500次代码提交 via 1.5万程序员;
自动测试每天运行7500万次;
0.5%的工程师致力于开发工具;
是的,你没看错,整个Google 只有一个代码仓库。
这些挑战是催生谷歌可靠性工程的重要需求来源。Filecoin的任何一个挖矿项目的复杂度,都还没有达到谷歌的级别。其原因主要是因为区块链存储行业处于起步阶段,没有大规模应用的需求。
另外,谷歌还开创了SRE领域。在行业内,谷歌出版了两本关于SRE的原则和最佳实践的书。
然而,在处理生产环境中各种故障事件的紧张时刻,团队的实际响应和调试方法常常与理想的最佳实践有所不同。
这让我重新深度思考组织问题和流程问题。
二、组织的结构和动力学
谷歌认为,高效组织和低效组织之间存在着结构上的差异。
高效组织不仅在开发各种功能的技术能力方面付出巨大努力,还总是平等地关注个人、团队和技术的协作方式,因为这些方式将对它们所属的过程做出正向或者反向的摩擦力。
高效组织是过程导向,低效组织的“孤岛”自治。而且在高效组织中,功能集成不仅仅是说说而已,它是每天各级管理的具体细节。
谷歌认为,高效组织的动力学来自不断改进的组件和过程。无论个体还是团队工作,无论是否有设备,高效组织不愿意接受模棱两可,其将功能作为流程的一部分进行管理,并提前对以下内容进行详细说明:
预期产出;
谁负责什么工作,顺序如何;
产品、服务与信息如何从上一步的负责人手上,递交到下一步的负责人手中;
完成每一部分工作的方法。
更为全面地,高效组织的结构和动力学可以总结为史蒂夫·斯皮尔能力模型:
能力1:在问题发生时马上就能发现;
能力2:一旦发现问题立刻蜂群式解决(Swarming),并将此记录下来储备成新知识;
能力3:在整个公司范围内传播新知识;
能力4:以开发为主导。
高效组织善于在问题发生的时间和地点解决问题。他们同样擅长于:
在问题出现之前控制问题;
诊断和解决问题,使问题不再发生。
在这样做的过程中,高效组织建立了关于如何管理系统的深层知识,将不可避免的前期无知转化为知识。
高效组织使新知识不仅对发现它的人可用,而且对整个组织都可用,从而使其力量成倍增长。而且其不仅分享发现的解决方案,还分享发现这些解决方案的过程——学习了什么以及如何学习。
高效组织会控制他们的问题并传播他们的发现,而低效组织(即他们的竞争对手)允许问题持续存在并传播到更大的系统中,因为即使找到了解决方案,也会保留在被发现的地方。这意味着,经验积累使高效组织具备了乘数效应。
我们在实际工作中,借鉴区块链的思想,创新地推动开发、测试和运维之间的去中心化协作,以促进在问题出现时快速发现,然后蜂群式解决问题。去中心化沟通使得知识自然在多个团队之间流动。在这个过程中,开发团队起到了主导作用。
三、事前测量一切
Measure Everything:Cannot improve what we don't measure.
没有测量,就没有改进。系统越复杂,感受越深刻。事前测量一切和事后剖析免责是我秉持的两个重要文化理念。
四、事后剖析免责
blame-free PostMortems,或称blameless post-mortem。
你会发现,如果组织文化能保证事后评估的安全性,就会激发一种惊人的动力:工程师们开始相互竞争,争取发现更大的错误。这将产生大量的组织学习成果,并与史蒂夫·斯皮尔模型相符:这样做使我们能够在灾难性事件发生之前,很早就开始不断发现问题,然后加以解决。
事后剖析免责行得通的原因是我们都是工程师,我们热爱构建和改进系统。这种暴露问题的环境创造了一个非常令人感到安全、兴奋和满意的工作环境。
五、关注人:区分工程师的心智模型
人是故障响应者,因此区分心智模型非常重要。故障响应者一般分为两类:软件工程师和运维工程师(在谷歌称为SRE工程师)。在生产环境中,不同故障响应者对故障的响应是完全不同的。
软件工程师更倾向于在调试工作流中更早地查阅日志,在工作流中他们查找错误,从而指出故障发生的位置。
运维工程师或者SRE工程师更依赖于一种更通用的调试方法:因为运维工程师经常对多个服务待命,基于系统的已知特征,他们应用一种通用的方法来调试和维护。
他们在服务运行状况指标中寻找常见的故障模式(例如,请求的错误和延迟),以隔离问题发生的位置,并且通常只在无法确定最佳解决策略时才深入日志。
六、谷歌故障响应流程和解决模式
以上内容基本上都是从组织的文化层面来谈分布式系统的调试问题。下面通过谷歌的真实案例讨论生产环境中的故障响应流程。
在生产环境中,无论是开发工程师,还是运维工程师,都会遇到不同维度的事件,这些维度具备一些常见的模式:
规模和复杂性:问题的爆炸半径(即其位置、受影响的系统、受影响的用户旅程的重要性等)越大,问题就越复杂;
响应团队的规模:随着越来越多的人参与到调查中,团队之间的沟通渠道就会增加,团队之间更紧密的协作和交接就变得更加关键;
故障原因:谷歌的oncall人员主要面对以下六个常见问题:性能问题、代码变更、配置变更、依赖问题(服务本身或服务的依赖)、基础设施问题(网络或服务器宕机)以及外部流量问题。当然,安全性或数据正确性问题也需要关注,但一般属于特定的业务范畴;
检测:人工检测或者机器检测,一些常见的机制包括以下告警:白盒指标、合成流量、SLO(服务水平目标)违规和用户检测到的问题。
典型的调试过程包括下图所示的阶段和子阶段。在工程师调试问题时,这些阶段经常会重复出现,每个阶段都可能会以非顺序、有时甚至是循环的方式出现。
从检测到解决,调查通常是时间敏感的——特别是当问题影响到最终用户体验时。谷歌采用的原则是:先恢复服务,再排查问题。在发现根本原因之前,运维人员总是会试图缓解问题或对问题“止血”。止血之后,开发人员通常会对代码进行更深入的分析,并应用措施防止类似的情况再次发生,具体操作如下:
检测
运维人员通过告警、客户申诉或主动调查来发现问题。这个过程的一个常见的问题是:这个问题的严重性是什么?
检测过程中的可观察数据包括给定服务运行状况的时间序列指标,执行宽度优先搜索,以确定系统的哪些组件出现故障。oncall人员通常只在组件故障之后才开始追踪日志,然后需要深入研究特定问题。
分类
运维人员的目标是通过检查问题的爆炸范围(问题的严重性和影响)来快速评估情况,并确定是否有必要升级(召集其他团队,通知内部和外部的干系人)。当更多的信息进入时,这个阶段可能在单个事件中发生多次。
这个过程的常见问题是:我应该升级问题吗?我需要立即解决这个问题,还是可以等一等?这次宕机是本地的、区域性的还是全球性的?如果宕机是本地或区域性的,那么它会变成全球性的吗?
调查
oncall人员或者工程师会对潜在问题提出假设,并使用各种监控工具收集数据,以验证或反驳理论。然后,oncall人员试图缓解或修复潜在的问题。在单个事件中,这一阶段通常会发生多次,因为oncall人员需要收集数据来验证或反驳有关问题起因的任何假设。
这个过程的常见的问题是:错误和延迟是否达到峰值?需求有变化吗?这个服务的健康程度?这是虚惊一场,还是问题确实存在?出问题组件的依赖关系是什么?服务或依赖关系是否发生了变化?
解决
oncall人员的目标是确定什么措施可以解决这个问题。有时,解决尝试可能使问题变得更糟,或对其依赖的服务之一造成负面的连锁反应。补救或问题的完全解决通常花费所有调试步骤中的最长时间。在单个事件中,这个步骤可以而且经常发生多次。
这个过程的常见问题是:应该采取什么解决方案?你有信心这是适当的解决方案?这种方案可以解决问题吗?
需要注意的是,在上述整个过程中,沟通起到非常重要的作用。oncall人员记录他们的发现,与队友一起进行调试,并根据需要在团队内外进行沟通。
在谷歌的上述案例中,还有一个问题解决和事后剖析的循环阶段。事后剖析的目标是找出潜在的问题,以防止问题再次发生。此步骤通常发生在问题得到解决并且不再对时间敏感之后,并且可能涉及重大的代码更改。在此阶段编写后期分析文档。
事后剖析的常见问题是:哪里出了问题?问题的根本原因是什么?如何使流程和系统更具弹性?
七、日志不是调试工具,截图更不是
我们在工作中,经常使用的日志和截图,这对于小规模的系统非常有效,团队也乐于这么做。
但对于大规模分布式系统的调试来说,日志和截图明显不再适用。下面是谷歌关于工具的一些原则:
谷歌在很大程度上依赖于各种可视化工具来排除不熟悉的问题并尽可能快地恢复服务。相关工具:Graphite、InfluxDB + Grafana和OpenTSDB。这些工具和下面提到的其他工具都不是谷歌使用的工具,也不推荐使用,但它们是有用的开源工具;
创建一个框架,让开发者可以轻松地把监控插入到框架中;
使用大量存储专门存储监控数据。历史数据必须可用,以便在恢复停机后可以进行故障排除。停机完全是为了恢复服务,故障排除是稍后在清醒时所做的工作。开发人员经常参与到故障排除过程中,因为他们对系统有更深入的了解。恢复不应该导致停机监视数据丢失;
对于关联事件,事件图非常有用。发挥人类的模式匹配能力,编写机器人来完成这个任务是很困难的;
有时需要深入到可视化进程跟踪的进程级别来识别性能问题。相关工具:Performance Co-Pilot + vector;
网络流量和容量。如果存储都很慢,问题可能是网络问题。如果你正在查看存储系统,并不能找出它为什么很慢,则查看网络。相关工具:Cacti、Observium、Nagios;
当所有其他方法都失败,则查看日志文件。你不希望查看日志文件。你需要一个具有更多类似SQL查询的系统,这样就可以深入研究日志。日志应该易于使用和理解。相关工具:ElasticSearch + Logstash (+Kibana)。
以上,我们浏览了谷歌关于大规模分布式系统调试的组织文化、工程实践、响应流程和调试工具,在各种参考文献中间的取舍也包含了我的思考。
谷歌的经验沿袭了学术研究和工程实践的交叉路线,并且具有大型组织实施的经验。系统调试的一个重要的目标是防止同一类问题重复出现,或者在不可避免的情况下将影响降低到最小。
学习谷歌的经验,站在巨人的肩膀上,也是一种有效的从他山之石学习事后剖析的方法。
参考资料
《Debugging Incidents in Google's Distributed Systems》
https://queue.acm.org/detail.cfm?id=3404974
《Book Review: "The High Velocity Edge" By Dr. Steven Spear》
https://itrevolution.com/devops-book-review-the-high-velocity-edge-by-dr-steven-spear/
《Uncovering The DevOps Improvement Principles At Google (Randy Shoup Interview)》
https://itrevolution.com/uncovering-the-devops-improvement-principles-behind-google-randy-shoup-interview/
《Postmortem Culture: Learning from Failure》
https://landing.google.com/sre/sre-book/chapters/postmortem-culture/
《How Does Google Do Planet-Scale Engineering For A Planet-Scale Infrastructure?》
http://highscalability.com/blog/2016/7/18/how-does-google-do-planet-scale-engineering-for-a-planet-sca.html
《How Google Backs Up The Internet Along With Exabytes Of Other Data》
http://highscalability.com/blog/2014/2/3/how-google-backs-up-the-internet-along-with-exabytes-of-othe.html
关联阅读
《谷歌Colossus文件系统的设计经验》
https://mp.weixin.qq.com/s/yviATMiqjeggemzZ0bBh-A
《谷歌可靠性工程的设计经验》
https://mp.weixin.qq.com/s/k02mCRxN19k7fLL6_zJ1Wg
《Filecoin太空竞赛的意义》
https://mp.weixin.qq.com/s/2Sk1aAiHJNqggz_8mg7fGg
作者丨tashi
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721