“LinkedOut” 失败注入测试框架

  • Daniel Bryant
  • 冬雨

2018 年 7 月 11 日

话题:DevOps语言 & 开发架构

领英工程团队最近更详细地讨论了他们的“LinkedOut”失败注入测试框架。该框架支持围绕应用程序和服务弹性的假设生成数据,并允许通过 linkin LiX a/B 测试框架或通过 cookie 中的数据向特定请求注入失败。可以测试的失败场景包括错误、延迟和超时。LinkedOut 项目是更大的“水熊(Waterbear)”计划的一部分,该计划鼓励领英的每个团队为弹性工程贡献自己的力量。

领英网站可靠性高级工程师罗根•罗森最近在领英工程博客上写了一篇文章:“LinkedOut:一个请求级失败注入框架”。这篇文章一开始就指出,在复杂的分布式技术堆栈中,重要的是要理解出问题的地方,还要知道这些故障如何将它们自己展示给最终用户。工程师应该假设“任何可能出错的地方,都会出错”。

向分布式系统注入故障的方法有很多,但是最细粒度的方法是在请求级别。Netflix 的 chaos/resilience engineering 团队之前已经讨论过他们如何创建失败注入测试 (FIT)框架,并最终演化为Chaos Automation Platform (ChAP),以这种方式注入失败。类似地,领英站点可靠性工程 (SRE) 团队在 2017 年末建立了Waterbear 项目,旨在帮助开发人员通过复制系统故障和调整框架以优雅和透明地处理故障,“直面弹性问题予以解决”。由此产生了 LinkedOut 失败注入测试框架,它支持请求级失败注入。

核心上,LinkedOut 在组织的Rest.li 栈中是一个“破坏者”请求过滤器,Rest.li 是一个 Java 框架,它允许开发人员轻松地创建使用 REST 风格通信的客户端和服务器。这项工作的开源部分可以在项目 GitHub 存储库中的r2-disruptor和 restli-disruptor模块中找到。LinkedOut 目前可以创建三种类型的失败:错误,当与请求的资源存在通信或数据问题时,Rest.li 框架会抛出几种默认的异常 ; 延迟,在过滤器将请求传递到下游之前,工程师可以指定一定的延迟 ; 以及超时,过滤器等待指定的超时时间。

工程师使用 LinkedOut 框架在开发时验证他们的代码是健壮的。这种验证被扩展到生产场景,为外部方提供健壮性的信心和证据。有两种调用破坏者的主要机制,同时将其对最终用户体验的影响降到最低。其中之一是 LiX, 它是领英的A/B 测试框架,以及领英上的功能控制,第二个是 Invocation Context(IC),这是一个领英特定于 Rest.li 的内部组件,允许将键和值传递到请求中并传播到处理请求的所有服务。

LiX 允许工程师在多个级别定位错误,从单个成员的单个请求到整个下游集群中一定比例的成员。

以 LinkedOut 引入有针对性的失败 (图片来自领英工程博客)

在领英中,服务调用图又大又复杂,最新的主页取决于其依赖树上 550 多个不同的端点,对于工程师来说,确保涉及这么多端点的每个失败场景能够平稳回退是非常困难的。因此,SRE 团队创建了一个服务账户 (不与真正的成员关联),并允许它访问所有的领英产品。

为了自动测试 web 页面,团队利用了领英的一个内部框架,该框架允许进行大规模的 Selenium 测试。它们通过一个 cookie(只在内部网络上运行) 向调用上下文 (IC) 注入中断信息,对用户进行身份验证,然后加载测试中定义的 URL。团队考虑了几种在注入失败之后判定成功的方法,但是在框架的第一次迭代中,他们决定为“oops”(错误) 页面和空白页面提供默认的匹配器。如果 Selenium 加载的页面匹配到这些默认模式中的任意一个,那么他们会认为页面没有平稳退化。

在讨论经验教训时,罗森谈到创建的服务账户并不总是反映真实用户在领英上的体验。例如,SRE 创建了一个测试来检查配置文件视图页面上的平稳退化,而最初每个下流的失败都会导致测试失败,这意味着页面返回了一个错误。可是无论如何以测试用户登录时,都会出现问题:因为这个测试用户没有连接领英,所以没有人在访问它的配置文件,于是配置文件视图页面就会返回一个错误,即使没有注入任何失败。解决办法是通过访问测试用户的配置文件来提供相关的数据,但是它带来的一个问题是:“测试用户并不总是很好地代表人们在领英上看到的东西”。避免这种情况的下一步计划是允许 LinkedOut 的用户提供他们自己的测试用户,他们可以预先填充数据。

在领英,由于 LiX 实验框架的成熟和强大,通过特性目标 (标记) 触发故障的机制很简单。工程师根据他们指定的失效参数创建一个目标实验。一旦实验被激活,中断过滤器通过 LiX 客户端获取变更,并让相应的请求失败。使用 LiX 还能让工程师很容易地“在几分钟内”终止那些已经出错或者对最终用户产生了不恰当影响的失败计划。

调用上下文注入机制允许通过 cookie 指定中断数据,在浏览器中进行快速、一次性的测试。为了发现 web 页面创建过程中涉及的下游服务,工程师们在领英中使用了一个名为“调用树”的服务,该服务在处理请求时使用服务生成的 Kafka 事件,并构建一个相应的调用树来显示所涉及的所有步骤。调用树允许将分组密钥设置为请求中的 cookie,它将把给定请求找到的所有调用树链接在一起。SRE 团队开发了一个 Chrome 扩展,使工程师在执行测试时可以更容易地进行服务发现和调用上下文失败注入。一旦工程师为所有适用的资源选择了失败模式,扩展将为这些失败创建一个损坏的 JSON blob,设置一个将其注入调用上下文的 cookie,然后注入这些失败去刷新页面。

尽管最近的博客文章侧重于技术方面的失败注入, 但前一个帖子“在领英使用 Waterbear 进行的弹性工程”讨论的是建立一个支持型文化的重要性,关注的是弹性测试的人性化的一面, 并确保混乱的测试是设计出来的,是遵循科学的方法和创建的假说运行的。

在领英,SRE 一直与服务所有者和他们的团队在一个名为“水熊”(Waterbear) 的项目上进行跨职能的协作 (这个项目昵称为tardigrade(熊虫,一种缓步类爬行动物),这是一种出名的耐药生物,能在真空空间中生存下来)。这篇文章建议 Waterbear 应该被认为提供的是“应用恢复力”服务 ;SRE 团队自己掌控领域和问题,以及“度量、分析和提供最佳实践,以帮助应用程序所有者和工程团队提高每个应用程序的弹性”。领英 SRE 的核心价值观之一是“解决问题,而不是人”,这反过来也反映了公司的价值观,“像负责人一样行事”和“人际关系很重要”。

让大家知道,服务所有者为解决问题而创造更加积极的环境时出现问题,不会遭到羞辱或言语攻击。这也使 SRE 组织更容易去影响整个工程团队的决策过程,以便对共享基础设施进行更改。

稍后一篇博文总结说,开发团队和领导团队一直非常支持 Waterbear 和领英。

只要我们有科学的方法来验证我们对失败的假设,限制爆炸范围的能力,有能力推出清晰的行动项目来提高系统的恢复力,并且可以构建适当的工具 / 系统来让运行这样的测试变得非常简单,领英的每个团队都可以为弹性工程工作做出贡献。

有关领英的其他信息可以在领英工程博客和及其相应的Rest.li GitHub库中找到。

查看英文原文:Chaos Engineering at LinkedIn: The “LinkedOut” Failure Injection Testing Framework

DevOps语言 & 开发架构