混沌工程

您希望在代码调试期间看到的最后一件事是混乱 但是,如果这种混乱是由开发人员控制和启动的,该怎么办? 为什么要在应用程序的平稳操作中故意安排动荡,在发布重要功能时如何 使人安心, 以及在混乱工程的实践中确实有用的地方 ,请在领先的AppsCast播客和Pavel Osipov之间的对话中阅读PavelOsipov。



Alexey Kudryavtsev:大家好! 今天,我们的来宾是Mail.ru Cloud的Pavel Osipov,我们将与他们讨论混沌工程。

帕维尔·奥西波夫(Pavel Osipov):大家好! 六年来,我一直在管理Mail.ru Cloud的开发。 在这段时间里,我们积累了许多经济测试的实践,其中之一就是混沌工程。 通过这种做法,您可以进行一系列受控实验,以识别敌对环境中系统的运行状况。 根据这些实验的结果,您将获得有用的见解。 例如,您不太可能定期查看系统在不稳定网络中的行为。 如果您的用户经常在地铁上旅行或在酒店的wifi环境中休息,则网络的稳定性不如程序员的工作场所。 每次在海上度假后,我都会带上完整的“投资组合”日志,记录应用程序出了什么问题。

就个人而言,繁琐的人工混乱使我获得了额外的信心,即使一切在应用程序之外都是不好的,也一切都会好起来的。

在某些情况下,我比手动测试更信任手动混乱。

看到混乱的根源


Alexei Kudryavtsev:这种做法的根源是什么?

Pavel Osipov:这是服务器实践,那里还有很多问题。 我们已经习惯了技术债务的概念,并且在西方国家也存在黑债务 -在复杂的系统中不可避免地会产生隐藏的债务。 与技术债务不同,在技术债务中,我们自觉地从现在借来了未来的时间,而隐藏的债务在创建系统的阶段是不可见的。 它发生在组件或硬件与软件的交汇处,并可能导致一系列问题:某个组件发生故障,另一个组件重叠,现在整个系统都处于瘫痪状态。

例如,在2016年,由于级联数据库关闭,Facebook停留了2.5小时。 然后,检查配置文件有效性的系统不仅在缓存子系统中,而且在作为主要来源的数据库中,都开始错误地删除它们。

我非常喜欢接受Odnoklassniki的Oleg Anastasiev进行的有关进行演习以防止基础设施事故的采访。 他们有三个数据中心,应该24/7处于警报状态,但是每季度发生一次故障。 他们在生产中进行此类练习。 一方面,这似乎很可怕,因为如果发生不可预测的事情,则整个数据中心将掉落,并且无法在产品上使用。 但另一方面,此过程是受控的,如果出现问题,您将立即看到它,将其停止,一切都将恢复。 如果这种情况发生在战斗寿命中,那么将其重新打开就行不通了,而且对停机原因的分析将持续很长时间。

混乱在移动开发中的好处


Daniil Popov:到目前为止,我们正在谈论服务器开发,在这种情况下,微服务非常流行,并且可能导致级联中断。 您能否提供更多示例说明在移动开发中通过混沌工程检查哪些内容?

Pavel Osipov:我最喜欢的示例是应用程序日志记录。 在测试条件下,我们对该应用程序的操作可能非常温和:我们进入了帐户设置,单击“退出”按钮,应用程序退出,并且在查看登录屏幕时,一切似乎都很好。 用户通常有更多的特殊情况。 例如,客户端通过Web界面更改了密码,或者其他设备上发生了大量日志,并且刷新令牌被替换。 该记录不在使用用户帐户的窗口中发生,而是例如在全屏照片查看器时发生。

我们发现许多情况下,在应用程序的不同位置登录会导致诸如内存泄漏的后果。 具有完成块的同一位观看者可以获取一项至关重要的服务,最终导致泄漏。

我们使用混沌工程来模拟条件。 该系统具有一项服务,该服务透明地针对高级应用程序服务使用应用程序的刷新令牌更新应用程序访问令牌。 我们引入了混乱,在这种混乱中,服务以某种程度的概率破坏了令牌,而不是更新令牌,并且每个开发人员每天都在一个意想不到的地方遇到日志。

由于这一点,我们发现了iOS中UIKit的一个有趣行为:如果突出显示一个扎根的ViewController时,从该窗口模态阻止了另一个窗口,则扎根的ViewController会泄漏并永远保留在系统中。 如果同时ViewController具有指向服务的链接,根据体系结构的逻辑,该链接必须在一个实例中存在于系统中,那么就无法避免问题。 例如,Cloud拥有照片自动加载服务,如果系统中保留了两项这样的服务,它们将做很多不必要的工作,并将设备电池的充电速度提高两倍。

另一个奇怪的情况。 当iOS 8出现时,扩展存在问题:在某些设备上,当给出了应用程序设置中的所有权限时,系统在启动时指出该应用程序无权访问共享应用程序组。

混乱的类型


丹尼尔·波波夫(Daniil Popov):混沌会根据兴趣或配置自动引入系统,但是人们是否需要看一下才能了解出了什么问题?

帕维尔·奥西波夫(Pavel Osipov):混沌是不同的:手动和自动。 对于操作系统来说,该应用程序无权访问共享应用程序组,而扩展程序无法访问共享资源和数据库,则使用手动混乱,并使用应用程序系统设置中的对勾标记将其打开。 质量检查小组的成员可以轻松地对此建模。

有自动混乱。 特别是,这些错误是根据我们的后端微服务建模的,以及与更新令牌相关的混乱。 结果是不同的。 可以通过视觉观察确定行进的布局。 有些地方可以让您以自动模式检测异常。 例如,在我们的应用程序中,将自动检测内存泄漏。 系统中有两个IoC容器。 一个管理者是全局服务的生存期,它与应用程序本身的生存期重合,另一个容器是与用户在时间上重合的服务管理者。 每个创建服务的IoC容器都会检查它是否存在于一个实例中。

让我们回到带有日志的示例。 在某个地方,突然发生了登录,开发人员重新输入了该帐户以继续工作。 此时,IoC容器报告发生了内存泄漏,并且理论上应该在一个实例中存在的服务再次被检测到。

什么时候是混乱的时间?


Alexei Kudryavtsev:是什么导致实施该做法?

帕维尔·奥西波夫(Pavel Osipov):我们是出于降低测试成本的需要而来的。 如何处理razlogin的相同问题? 您可以编写泄漏的单元测试,也可以困惑并编写UI测试。

混沌工程是最便宜的做法,因为它不依赖于用户案例,而是对所有用户案例自动起作用。

第二个触发因素-在引入该实践之前,在我们的崩溃报告中,经常观察到具有相同根本原因的类似崩溃。 例如,发生崩溃的原因不是因为配置文件中的系统登录,而是因为用户当时正在浏览图库。 情况不同,不可能测试razlogins的所有组合。 因此,我想提出一些使流程自动化的方法。

混沌工程学有一个相关的实践- 突变测试 。 在此实践中,我们将修改少量代码,并查看其如何影响测试。 如果在更改后测试正确执行,则意味着对于这些代码片段,测试还不够。

混乱工程和突变测试之间的区别在于,我们不会自动更改生产代码本身,而是自动更改其环境。

Alexei Kudryavtsev:是否可以在不进行混乱工程的情况下定位原因并解决问题?

帕维尔·奥西波夫(Pavel Osipov):引发崩溃的原因没有一个。 每个案例都有其独特的方式。 例如,模态按钮出现在窗口顶部,这导致在破坏日志期间破坏性的ViewController泄漏出去。 无法预见您在记录期间拥有的窗口层次结构的所有组合。 发生泄漏和崩溃的混乱的工程本地化模式。

Alexei Kudryavtsev:您使用这种做法已有多长时间了?

帕维尔·奥西波夫(Pavel Osipov):我们在2012年项目开始之初就开始使用它,因为有必要对其进行快速开发,并且没有为大型测试分配时间。 而且,这不仅令人印象深刻,而且是积极的经历。

Daniil Popov:如果我的应用程序崩溃了,并且我需要在JIRA中启动任务,那么将来我该如何解决,如何重现这种情况?

帕维尔·奥西波夫(Pavel Osipov):没有通用的食谱。 混沌工程在应用程序调试时被激活,而在发行版本构建时被禁用,因此可以通过开发环境控制台中的日志看到这种情况,从中您可以了解如何将任务放入JIRA。

Alexei Kudryavtsev:您是否正在尝试创建可复制的行为,以便您的混乱系统将问题状态通知您,并建议在开始时将其输入配置中以重复此状态?

帕维尔·奥西波夫(Pavel Osipov):听起来像宇宙,并且可能在Redux之类的架构中。 如果体系结构允许您记录关键事件之前的所有操作,那么这是可能的。 我们不是这样。 这是我在电信部门担任服务器端编程员时所练习的。 有一些测试将子系统的入口随机化,并检查是否有足够的输出。 我们实现了以下要求:当使用随机输入进行的测试使系统崩溃时,在负责自动化测试的程序中,输入请求的所有必需参数都被推迟,以便可以重现。

在应用程序中应用混乱


丹尼尔·波波夫(Daniil Popov):将这种混乱情况手动引入代码中是否正确?

Pavel Osipov:是的,我们的网络客户端具有内置功能,您可以在其中提交配置,该配置描述了应复制的混沌参数。 基于配置,他决定将客户端请求代理到服务器,或者自行拒绝废话。 用于网络的层使您可以自定义微服务在后端引入的混乱。 如果微服务请求不需要授权,则对授权数据有效性中的错误建模是没有意义的。

我们不仅随机化所有内容,播放完美的代码,而且有意义地随机化用户可以在现实生活中复制的内容。

Alexei Kudryavtsev:除了网络和文件,您还随机分配什么?

Pavel Osipov:我们调试了将来自特定端点的响应随机化的做法,以分别对每个微服务的行为和混乱进行建模。 我们已经完成了将文件系统移至单独的子系统的工作,并且当应用程序尝试写入或读取文件时,我正在尝试对各种错误进行建模。 手动模拟对应用程序中共享应用程序组的访问,我真的想开始为应用程序的行为建模(当它以非常小的磁盘空间启动时),在该空间中甚至无法创建数据库。

Alexei Kudryavtsev:是您要做的吗?

帕维尔·奥西波夫(Pavel Osipov):原则上是。 我们还没有解决所有使用现有混乱发现的错误。 当然,增加混乱并转移到其他子系统很有趣,但是那样一来,我们将没有时间解决混乱。

混乱的地方在哪里? 您总是可以找到一个可以为应用程序创建另一个湍流的地方。 建立问题很重要。 由于观察到许多类似的问题,因此使日志记录混乱。

如果监视表明在其他子系统中没有特殊问题,则花时间对不可预见的情况进行建模是没有意义的。

这不适用于重要操作正确的计费。

Alexei Kudryavtsev:另一方面,我们不知道用户的情况-这本身就是混乱的,因为您不知道将其放置在哪里,而只需要对其进行仿真。

Pavel Osipov:您始终需要关注ROI。 当然,您可以重现最特殊的情况,但是如果它们是单个的,那么它们也许就不是关键性的,因此没有必要对它们进行建模。

引入混乱的挑战


阿列克谢·库德里亚夫采夫(Alexei Kudryavtsev):对您来说,哪些工作很容易完成,哪些造成了困难?

帕维尔·奥西波夫(Pavel Osipov):对于初学者来说,习惯于混乱是不寻常的,因为这不是一种常用的做法。 您会遇到很多错误,这很难适应。 在几乎每个屏幕上,您都可以获得一包“五百”或难以理解的“ 404”,服务器将响应一次。 只有随着时间的流逝,您才能适应所有这些无聊的事实,并且服务器的响应是由系统本身建模的。

当您拥有已启动的关键功能时,这很困难,您需要尽快完成它,然后razlogin突然弹出来代替积累请求。 例如,您需要正确地组成屏幕,并且需要成功完成所有请求,而且这种可能性很小,因此您必须经过几十次才能达到所需的状态。 在这种情况下,禁用混乱就成为一种对策,重要的是不要忘记再次打开它。

引起不满的另一点是在基础架构服务中使用混乱,产生了很多副作用。

丹尼尔·波波夫(Daniil Popov):那么,默认情况下,开发人员是否总是启用混乱功能?

帕维尔·奥西波夫(Pavel Osipov):好的。 有时,当您甚至不关心混乱和他可以为您复制的那些奇特的情况时,都会很烦。 您必须忍受,但是如果您的屏幕正在与网络集中工作,则始终可以调整混乱的程度。 另一方面,混乱可能会在您所寻找的地方而不是从开发此功能的开发人员那里发现问题。 碰巧您的功能(其中添加了混乱)会导致影响您同事功能的后果。 如果仅在特定的发展时刻才会包括混乱,您将不会知道。

混乱的含义是识别大量组件交互作用中无法预料的后果。

如果您以精确而精确的方式包括混乱,那么这些罕见但目标明确的镜头将是看不见的。

Daniil Popov:混乱会妨碍代码的可读性吗?

帕维尔·奥西波夫(Pavel Osipov):将混乱引入系统之外时,坚持使用完成的混乱,然后是的,看起来很混乱。 在我们这里,由于长期的使用经验,混乱是有机地编织到系统中的,并且是如此孤立,以至于您在代码中没有注意到它。

Alexei Kudryavtsev:您发现了很多罕见的案例,将其修复,并且代码被拐杖包围。 这会使应用程序逻辑复杂化吗?

Pavel Osipov:这始终是我们代码的重要组成部分,但否则,不会编写大型生产应用程序。 当然,这完全取决于开发人员的技能,开发人员知道如何修复代码,以免影响眼睛。

引入混乱的优点


丹尼尔·波波夫(Daniil Popov):引入混沌工程后,是否有任何量化指标得到改善?

帕维尔·奥西波夫(Pavel Osipov):对我来说,最重要的指标是当我发布要发布的功能时内在的内心平静。

阿列克谢·库德里亚夫采夫(Alexey Kudryavtsev):和平不能卖给商业。 如何争论公司引入混沌工程?

帕维尔·奥西波夫(Pavel Osipov):由于存在自动测试功能,因此混沌工程技术为测试人员节省了时间。 引入混乱做法后,与razlogin发生的相同崩溃几乎从我们的JIRA中消失了。

当您获得快速反馈时,混沌工程会对发布周期产生有益的影响。 完成的功能进入测试是一回事,很长一段时间后,您会获悉所发现的错误数量,而拥有可以在整个调试程序中运行的机器人测试仪则完全不同。

我有信心,单元测试的结果要比下载数千个文件时混乱的50%低得多。 有了这样的负载,所有最令人难以置信的组合肯定会得到解决。

向谁学习,从哪里开始?


Alexei Kudryavtsev:为此您使用了哪些工具? 采取开放图书馆还是在开放源代码中撰写和发布?

Pavel Osipov:我们已经发布了一个开放源代码的网络库 ,但是没有专门的工具。 我所知道的唯一一个是Netflix Chaos Monkey ,它随机地“运行” AWS实例并终止它们,以查看是否熄灭了一定数量的容器是否一切正常。 我相信,在与相邻系统接触的地方编写配置文件并不需要深度自动化。

丹尼尔·波波夫(Daniil Popov):在哪里可以阅读有关混沌工程的更多信息?

帕维尔·奥西波夫(Pavel Osipov):首先, 《混沌原理》网站 ,该主题的所有资源都链接到该网站 。 其次, 学习混沌工程混沌工程可观测性的书籍。

通常,混沌工程是常识的实践,而基础知识则不存在。 您始终需要了解在哪里灌输混乱。 同时,每个应用程序的混乱情况都是唯一的吗? 并且您必须首先了解需要与您一起实施的内容。

Alexei Kudryavtsev:如果您仍然决定引入混乱,该从哪里开始?

帕维尔·奥西波夫(Pavel Osipov):首先分析系统中的问题,崩溃和原因。 在确定邪恶根源之后,您必须了解如何为导致问题的情况建模。 第三步是仔细引入混乱并控制它。

Alexei Kudryavtsev:在应用程序中可能会受到很多伤害,但是如何确定优先级呢? 哪里最好不要干涉?

帕维尔·奥西波夫(Pavel Osipov):没有虚幻的事物。 价格与尾气的比例很重要。 如果有丰富的系统API,则用您自己的包装器包装起来很昂贵。 如果您不完全了解某事,那么您将开始引起混乱,这在自然界是不可能的,并且将导致徒劳的斗争。 例如,如果整个UIKit或购物API都被混乱所覆盖。

混乱不是随机戳,而是对模拟情况的清晰理解。

Alexei Kudryavtsev:您建议实施这种做法有多少?

Pavel Osipov:我通常建议从引入混沌工程开始,而不是单元测试,因为这是最便宜的做法。

对混沌工程感兴趣? 在10月21日至21日于圣彼得堡举行的秋季AppsConf上赶上Pavel Osipov,他将在此发表有关键值数据库的新报告。

Source: https://habr.com/ru/post/zh-CN464723/


All Articles