加快生产故障排除的 7 种调试技术
已发表: 2022-03-11为应用程序提供生产支持是软件开发中最具挑战性的方面之一。 开发人员被分配到维护团队并致力于修补应用程序上的错误。 但是,如果发生生产中断,它们也可以随时待命,在这种情况下,它们会努力使应用程序尽快回到正轨。
本文旨在提供一组精心策划的建议,以便您可以防止生产中的错误,并更快地发现问题。 在生产环境中处理这些应用程序是一项复杂的任务:通常没有可用的文档,或者应用程序是在遗留技术堆栈中编写的,或者两者兼而有之。 培训课程很少,并且通常会被要求为您知之甚少的应用程序提供支持。
许多开发人员没有在生产环境中处理应用程序的经验。 生产环境中发生的一系列问题会导致错误和中断,通常会给公司造成数千甚至数百万美元的收入损失。 此外,由于大多数开发人员没有接触过环境,他们不断地犯一些错误,进而导致这些问题。 通过从生产经验中进行教学,此提示列表应该可以减轻您的工作痛苦。
提示 #1:删除或自动化应用程序运行所需的所有配置。
在新服务器上安装软件需要多少配置? 过去,每次团队中有新开发人员时,有时可能需要三天才能完成。 安装应用程序需要许多必须手动执行的步骤。 随着时间的推移,软件发展到与这些指令不兼容的新版本,当然,指令通常不会更新。 突然之间,您花费的时间比必要的多,只是为了启动和运行应用程序。
随着容器化的出现,提供一种立即启动和运行应用程序的方法变得更加容易,零配置以及额外的好处是,由于 Docker 映像是自包含的,因此您运行的速度要低得多使用不同版本的操作系统、语言和框架时遇到问题的风险。
同样,简化开发人员设置,因此启动和运行不需要太多时间,包括 IDE 设置。 开发人员应该能够在不到 30 分钟的时间内从零变成英雄。
当生产问题发生时,有时您最好的专家可能不在(例如,休假或生病),而您希望您提出的任何人都能够快速解决它。
提示 #2:不要落入技术栈汤陷阱。
使用的技术越少越好。 当然,有时,您必须使用正确的工具来完成这项工作。 但是,请注意不要过度使用“正确的工具”。 如果你喝得太多,即使是喝水也会导致严重的健康问题。 添加到技术堆栈中的每一种新语言和框架都必须经过一个明确定义的决策过程,并仔细考虑影响。
- 不要仅仅因为您需要
StringUtils
类而添加新的框架依赖项。 - 不要仅仅因为您需要编写一个快速脚本来移动文件而添加一种全新的语言。
当库变得不兼容或在框架本身或其传递依赖项上发现安全威胁时,一大堆依赖项会让你的生活变得悲惨。
此外,请记住,增加的堆栈复杂性使得为团队寻找和培训新开发人员变得具有挑战性。 人们转移到其他公司的新角色,你必须找到新的。 工程团队的人员流动率非常高,即使是在那些以拥有丰厚福利和工作与生活平衡而闻名的公司中也是如此。 您希望尽快找到新的团队成员。 在技术堆栈之上添加的每一项新技术都会增加寻找新候选人的时间,并且有可能使新员工变得越来越昂贵。
提示 #3:日志记录必须引导您找到问题,而不是用无用的细节淹没您。
日志记录与评论非常相似。 有必要记录正在采取的所有关键决策以及在调试技术中使用的所有信息。 这并不简单,但只要有一点经验,就可以绘制出一些可能的生产中断场景,然后放入必要的日志记录以至少解决这个问题。 当然,日志记录与代码库一起发展,具体取决于出现的问题类型。 一般来说,您应该将 80% 的日志记录在最重要的 20% 代码上——使用最多的部分。 例如,重要信息是传递给方法的参数的值、子类的运行时类型以及软件做出的重要决策——即,它处于十字路口的时间,它选择了左还是右。

提示#4:处理意外情况。
非常清楚地标出代码的假设是什么。 如果某个变量应始终包含值 2、5 或 7,请确保它是枚举类型,而不是 int。 大规模生产中断的第一个来源是某个假设失败。 每个人都在错误的地方寻找问题,因为他们认为一些事情是理所当然的。
假设应该明确记录,并且这些假设的任何失败都应该引起足够的警报,以便生产支持团队可以快速纠正这种情况。 还应该有代码来防止数据进入无效状态,或者至少在这种情况下创建某种警报。 如果某些信息应该存储在一个记录中,而突然有两个记录,则应发出警告。
提示#5:复制发生在客户身上的问题应该很简单。
最困难的步骤之一始终是复制客户面临的问题。 很多时候,您将花费 95% 的时间来尝试复制问题,然后在您可以复制它的那一刻,修补、测试和部署只需几分钟。 因此,应用程序架构师应该确保复制问题非常简单和快速。 发生很多这种情况是因为,为了达到与客户相同的情况,开发人员必须进行大量的应用程序配置。 存储了许多记录,这些记录共同构成了客户所处的情况——问题是您作为开发人员必须准确猜测客户做了什么。 有时,他们执行了一系列步骤,他们只记得最后一个。
此外,客户将用业务术语解释问题,然后开发人员必须将其转换为技术术语。 如果开发人员对应用程序的经验较少,他们将不知道要询问缺失的细节,因为他们甚至还不知道缺失的细节。 将整个生产数据库复制到您的机器是不可行的。 所以应该有一个工具可以从生产数据库中快速导入模拟情况所需的少数记录。
假设客户对订单屏幕有疑问。 您可能需要导入他们的一些订单、他们的客户记录、一些订单详细记录、订单配置记录等。然后您可以将其导出到 Docker 实例中的数据库中,启动该实例,就像这样,您看到与客户看到的相同的东西。 当然,所有这一切都应该以适当的谨慎来完成,以确保没有开发人员可以访问敏感数据。
提示 #6:在应用程序中放置断点的位置应该很明显。
如果您有一个客户屏幕,则应该有一些客户对象,您可以在其中放置断点以在该屏幕上调试问题。 有时开发人员会陷入抽象热,并提出一些关于如何处理用户界面事件的非常聪明的概念。 相反,我们应该始终依赖 KISS 原则(保持简单、简洁、愚蠢),并为每个 UI 事件提供一个易于定位的方法。 同样,对于批处理作业和计划任务——应该有一种简单的方法来确定断点的位置,以评估该代码是否工作。
提示 #7:确保所有外部依赖项都明确记录在案。
理想情况下,在源代码控制系统的 README 文件中执行此操作,这样文档就不会丢失。 记录应用程序正常运行必须可用的任何外部系统、数据库或资源。 此外,请注意其中哪些是可选的,并添加有关如何在它们是可选且不可用时进行处理的说明。
超越调试技术
一旦在创建新功能或为系统提供维护时遵循这些建议,生产支持将变得更加容易,您的公司将花费更少的时间(和金钱)。 如您所知,在解决生产错误和崩溃问题时,时间至关重要——任何可以节省的时间都会对利润产生重大影响。 快乐编码!