07 软件开发:如何利用可观测性进行驱动? 你好,我是翁一磊。

在上一讲,我们说建立可观测性不仅仅是运维同学的责任,开发同学也应该积极地参与进来,因为代码是开发写出来的,他们是最了解系统和应用的。这节课,我们就更近距离看看可观测性驱动的软件开发,看看它如何更加有效地帮助我们分析生产环境问题,保障生产环境的服务可靠性。

测试驱动的软件开发

如今,在软件投入生产之前,需要先进行一系列的测试,这已经是非常标准的流程了。而你可能也早就听过它的英文首字母缩写TDD,测试驱动的软件开发(Test Driven Development)。

TDD指的是一个软件开发过程,它依赖于在软件完全开发之前将软件需求转换为测试用例,然后通过对所有测试用例的重复测试,来跟踪所有软件开发。

简单地说,测试驱动的软件开发包括下面这些流程:

  • 编写一个单元测试,描述程序的一个方面;
  • 运行测试,这个时候测试应该会失败,因为程序缺少该功能;
  • 编写“刚好足够”的代码,尽可能简单,以使测试通过;
  • “重构”代码,直到它符合简单性标准为止;
  • 重复上述步骤,直到找不到更多驱动编写新代码的测试。

更多详细的介绍,可以访问这个链接

测试驱动的软件开发,可以在许多潜在问题投入生产之前,通过在测试环境中的一系列验证,发现和捕获程序上的问题。

然而,如果你管理或维护过生产环境,你应该很清楚,生产环境是实际用户访问和使用产品的环境,它很多时候和测试环境是不一致的。在生产环境中很容易遇到测试环境中没有碰到过的问题,程序的代码也总是会存在一些测试没有覆盖到的地方。所以我们需要在生产环境中快速定位和解决问题的能力。

针对生产环境建立可观测性

生产环境不是一成不变的,它充满了各种可能性,因为这是真正的最终用户访问和使用软件的环境。工程师们应该有能力和自信来应对任何异常,原因就像我们上节课说的,可观测性不仅仅是基础设施工程师或者运维工程师的专属领域,更重要的是,软件工程师也必须采用可观测性并将其运用到自己的开发实践中,打破自己对于变更生产环境的恐惧感。

换个角度来看,当我们升级或更新了生产环境之后,如果有问题,也希望能够及时发现,及时排错,而不是等过了很久之后才发现问题。因为这时候开发往往已经进入到后续的新功能迭代阶段,再来处理之前迭代周期的功能开发,常常是事倍功半的。

所以说,我们需要针对生产环境建立可观测性。当代码发布在生产环境之后,开发同学也应该去看看软件程序在生产环境中实际的运行情况,检查功能是不是都符合预期,最终用户在使用时有没有遇到异常或者错误,有没有出现测试环境中没有碰到过的问题。如果开发对生产环境足够关注,将会在真正影响用户体验之前发现和解决很多问题。

可观测性驱动的软件开发

针对生产环境建立可观测性,具体要怎么做呢?

可观测性驱动的软件开发(Observability Driven Development,缩写为 ODD)鼓励开发团队在整个开发过程中考虑应用程序的可靠性和软件质量,利用工具或是开发人员的插桩来观测系统的状态和行为。可观测性并不是要直接调试代码逻辑,而是在每次新功能或者版本发布到生产环境后,检验生产环境的状态,帮助发现并定位潜在问题,找出系统中需要调试的代码所处的位置。

这里有一些最佳实践和准则可以遵守,包括建立文化、有意义的代码插桩,还有选择合适的可观测工具。

建立文化

开发不应该只是关注于产品功能的实现,也需要为系统整体的可靠性负责。在这个认知的前提下,我们也需要建立可观测性驱动的开发文化,鼓励开发更好地参与到可观测性的建立上来。

  • 拥抱失败:与其害怕失败,拼命避免失败,不如认清现实,那就是 100% 可靠的系统在现在这个时代是不存在的。所以我们首先需要承认,我们不可能预测到代码在生产环境中出现问题的所有方式。所以说,如果仍然只采取测试驱动的开发方式,是无法有效地编写所有的测试用例的。
  • 允许犯错:同样,也正是由于这个世界上没有 100% 可靠的系统,如果不能容忍一个因为无心之失引发的错误,那整个团队就会变得畏手畏脚,抵触改变,进入一种少做少错的状态。这绝对不是我们的初衷。我们事件后审查的目标应该是识别系统和流程中的弱点,并通过建立可观测性和工程化来避免这个错误再次发生。
  • 拒绝个人英雄主义:英雄文化是建立可观测性的文化的障碍。如果你的团队中只有极少数人拥有在生产环境中进行故障排除所需的知识,风险就比较大了。因为现代分布式系统比几年前的系统复杂得多,继续依靠少数人甚至一个人的能力来理解和调试这些系统是不可信的。我们应该去让大家都能够理解可观测性,学会使用工具分析问题,减少对少数“专家”的依赖。
  • 更新之后尽早排查:当开发人员把代码部署到生产环境后,应及时通过可观测性来查看生产环境的状态,而不是被动地等着最终用户反馈问题。构建系统的开发人员比任何人都更了解系统,如果及时注意到那些可以在早期修复的异常,可观测平台的效果就充分显现出来了。

鼓励有意义的代码插桩

但是,只有文化愿景是不够的,我们在代码设计阶段,就必须考虑和确定系统在生产环境运行时需要达到的目标。比如说,定义好服务水平目标 SLO,为了提供预期的服务质量,你需要什么程度的可观测性?你的用户关心什么?他们会注意到什么?试图找出可能出错的地方,以及提前发现错误的方法。

在明确了目标之后,我们应该将代码插桩视为重要的责任,并视为将其交付生产的要求。代码插桩主要包括下面几种类型。

  • 第一种类型,日志推荐,它是以 JSON 方式输出的。这个方式最重要的是在日志输出过程中能够添加与业务分割相关的标签(即我们常说的 tag),以便后续的日志分析统计。
  • 第二种类型是链路追踪。一般情况下,我们可以通过无埋点的方式进行追踪,但是如果开发工程师针对部分业务可以进行深入的埋点,或者集成更多业务相关的标签,那会更有意义。
  • 第三种类型是用户体验监测,即 RUM(Real User Monitoring)。如果前端或者 App 端开发工程能够将用户体验也纳入到整体的可观测性范围内,那么就可以进一步地保障用户的服务质量,更有效地发现和定位问题了。前端或者 App 端团队要对用户体验进行集成,可以采用插桩或集成更多业务相关标签等方式。
  • 最后,我们还可以建立统一的数据规范。例如,相同的指标命名规范、相同的日志格式、相同的链路系统(即使都遵循 OpenTelemetry 标准,仍会出现不同),定义串联整个系统的统一标签规范(如,所有错误都是 Status: Error)。

良好的插桩可以帮助你的组织更广泛地传播可观测性文化,减轻团队的负担,因为如果插桩提供了足够的上下文,运维或技术支持团队就能够解决更多问题,不需要频繁地寻呼开发了。

选择合适的可观测工具

就像我们在第 5 讲中介绍的,构建可观测性,并不是一定要完全依靠自己来搭建和研发,很多时候,选择合适的工具可以帮助你更有效率地达到目标。

有许多工具都自称是“可观测性工具”,但事实并非如此。这样一来,选择正确的工具就很重要了。一个好的可观测性工具需要具有下面几种能力。

  • 丰富的基础数据集成能力:好的可观测性工具要能通过这些丰富的数据来确定更精准的监测,并且可以尽量丰富记录真实的系统运行状态。
  • 强大的分析诊断能力:要保证系统的可靠性,一个重要的能力就是及时发现并定位可能造成系统不可靠的原因,或者在有问题的时候尽量缩短问题的持续时间,尽快找到问题根因并予以解决。我们希望,即使故障排除人员对应用程序和代码库不太熟悉,这个工具也能帮助你快速排除故障。如果你遇到了新的问题,它能为你提供探索和下钻的能力。
  • 灵活的自定义能力:每一个业务/服务,以及承载这些业务/服务的系统都是很特殊的,它们在云环境的部署形态,所使用的组件各不相同。因此,只有具备强大的自定义能力的平台才能为我们有效地提供可观测性,针对不同维度建立可视化,快速定位问题。
  • 数据的统一和联合能力:最后,我们还要确认这个工具是不是真的能够将数据统一起来,而不是将一堆单独的工具缝合在一起。我们不希望再在各种工具之间跳转,浪费大量时间去进行人为判断,而是希望工具可以替我们完成这一切。

小结

好了,这节课就上到这里。

在这一讲,我们重点讲述了测试和可观测性驱动的软件开发。使用测试进行驱动,可以依靠各种测试来检验代码的质量,但是生产环境和测试环境完全不同,你也无法完全预料最终用户使用你的产品和服务的方式,不能确定他们会遇到怎么样的问题。

而可观测性驱动的软件开发,能够帮助你更加清晰地了解在生产环境中,你的用户如何使用你的产品,遇到了哪些问题,包括那些你之前可能无法预料或者发现的问题。

可能你以前无法理解生产环境的实际运行情况,导向了一种不敢触碰生产环境的心态。而通过可观测性,开发工程师可以观测新功能发布到生产环境时的各种状态,将生产环境作为一个可观测、可交互的环境,这样就可以获取到最终用户的真实体验,用它来改进开发软件了。

思考题

在这节课的最后,留给你一道思考题。

你在工作中,是如何维护生产环境中系统和软件的可靠性的?有没有遇到在测试环境中无法复现的问题,又是通过什么方法来解决的?

欢迎你在留言区和我交流讨论,我们下节课见!

参考资料

https://learn.lianglianglee.com/%e4%b8%93%e6%a0%8f/%e6%b7%b1%e5%85%a5%e6%b5%85%e5%87%ba%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7/07%20%e8%bd%af%e4%bb%b6%e5%bc%80%e5%8f%91%ef%bc%9a%e5%a6%82%e4%bd%95%e5%88%a9%e7%94%a8%e5%8f%af%e8%a7%82%e6%b5%8b%e6%80%a7%e8%bf%9b%e8%a1%8c%e9%a9%b1%e5%8a%a8%ef%bc%9f.md