Fault analysis and debugging of microservice systems: Industrial survey, benchmark system, and empirical study

 

 该文章为《Fault analysis and debugging of microservice systems: Industrial  survey, benchmark system, and empirical study》中文翻译,原文PDF和翻译的word请查看下方百度云链接。

链接:https://pan.baidu.com/s/1aclkX-ZVbuM4o8sxJjJlTg
提取码:iws6

微服务系统的故障分析和调试:行业调查,基准系统和经验研究

摘要:微服务系统的复杂性和动态性对各种软件工程任务(例如故障分析和调试)提出了独特的挑战。尽管微服务在行业中很普遍并且很重要,但对微服务系统的故障分析和调试的研究仍然有限。为了填补这一空白,我们进行了一项行业调查,以了解微服务系统的典型故障、当前的调试实践和开发人员在实践中面临的挑战。然后,我们开发一个中等规模的基准微服务系统(在我们所知范围内是最大,最复杂的开源微服务系统),并在其上复制22个行业故障案例。基于基准系统和复制的故障案例,我们进行了一项实证研究,以调查现有行业调试实践的有效性,以及是否可以通过引入最新的分布式系统路径跟踪和可视化技术来进一步改进它们。结果表明,通过采用适当的路径跟踪和可视化技术与策略,可以改善微服务调试的当前行业实践。我们的发现还表明,对更智能的轨迹分析和可视化功能有强烈的需求,例如,通过将轨迹可视化和改进的故障定位相结合,并采用数据驱动和基于学习的推荐来进行可视化探索和轨迹比较。

关键词:微服务,故障定位,路径跟踪,可视化,调试

1.引言

微服务架构是一种体系结构样式和方法,用于将单个应用程序开发为一组小服务,每个小服务都在自己的进程中运行并与轻量级机制(通常是HTTP资源API)进行通信。微服务架构允许每个微服务独立开发,部署,升级和扩展。因此,它特别适用于在云基础架构上,并且需要频繁更新和扩展其组件的运行的系统。

如今,越来越多的公司选择从所谓的单体架构迁移到微服务架构。他们的核心业务系统越来越多地基于微服务架构构建。通常,大型微服务系统可以包含成百上千个微服务。例如,Netflix的在线服务系统使用约500多种微服务,每天处理约20亿个API请求;腾讯的微信系统可容纳20,000台机器上运行的3,000多种服务。

由于微服务的粒度极小且复杂,并且运行时环境的配置复杂,因此微服务系统非常复杂。微服务系统的执行可能涉及大量的微服务交互。这些交互大多数都是异步的,并且涉及复杂的调用链。例如,Netflix的在线服务系统每天涉及50亿次服务调用,其中99.7%是内部的(大多数是微服务调用);Amazon.com进行100-150次微服务调用以构建一个页面。微服务的动态性质使情况变得更加复杂。微服务可以具有在不同容器上运行并由微服务发现服务(例如,Docker swarm的服务发现组件)管理的数以千计的物理实例。实例可以在运行时根据扩展要求动态创建或销毁,并且在路径跟踪中对同一微服务的调用可以由不同的实例来完成。因此,迫切需要解决架构挑战,例如处理异步通信,级联故障,数据一致性问题,发现和微服务认证。

微服务系统的复杂性和动态性给调试带来了巨大而独特的挑战,因为开发人员需要推理不同微服务的并发行为并了解整个系统的交互拓扑。理解和调试分布式系统的基本有效方法是路径跟踪和可视化系统执行。但是,微服务系统比传统的分布式系统更加复杂和动态。例如,由于微服务实例可以被动态创建和销毁,因此微服务与分布式系统中的系统节点之间缺乏自然的对应关系。因此,目前尚不清楚用于微服务系统的分布式系统的最新调试可视化工具是否能够或如何良好地使用。

尽管微服务在行业中很普遍并且很重要,但是关于该主题的研究仍然很有限,在软件工程研究界只有很少的关于微服务的论文,而在大型会议上则更少。现有研究集中在有关微服务的广泛主题上,包括设计、测试、部署、验证、组合、架构恢​​复、旧版迁移和运行时适应。关于微服务系统的故障分析和调试的研究很少。而且,对微服务的现有研究通常基于微服务很少(例如5个或更少的微服务)的小型系统。缺乏非平凡的开源基准微服务系统导致研究团体可以生产的产品与行业实践真正需要的产品之间存在差距。吸引人的是,从业人员和研究人员开发并共享一个通用的微服务基础结构,该基础结构可以模拟典型微服务应用程序的生产环境,以进行可重复且针对行业的经验研究。

为了填补这一空白并进行与微服务相关的实践研究,我们对微服务系统典型故障的故障分析,当前的调试实践以及开发人员面临的挑战进行了行业调查。我们的调查表明,当前实际使用的技术是有限的,开发人员在微服务调试中面临着巨大的挑战。然后,我们进行一项实证研究,以进一步调查现有行业调试实践的有效性以及最新的调试可视化工具是否可以促进该实践。

为了使我们的研究成为现实,并为广大研究团体提供有价值的实践基准,我们开发了一个名为TrainTicket的中型基准微服务系统。在我们的知识范围内,我们的系统是最大,最复杂的开源微服务系统。在该系统上,我们复制了行业调查中收集到的22个代表性故障案例。基于基准系统和复制的故障案例,我们通过扩展用于分布式系统的最新调试可视化工具,从经验上评估执行路径跟踪和可视化对微服务调试的有效性。根据研究结果,我们总结了我们的发现,并提出了未来研究的方向。

在这项工作中,我们做出以下主要贡献:

l  我们对行业微服务系统进行了调查,并报告了有关典型故障,当前调试实践以及开发人员面临的挑战的故障分析结果。

l  我们开发了一个中等规模的基准微服务系统(在我们所知范围内是最大,最复杂的开源微服务系统),并在其上复制了22个代表性故障案例。该系统和复制的故障案例可以用作研究社区的基准,以进一步开展与微服务故障分析和调试相关的实践研究,并可能进行与微服务相关的其他的实践研究。

l  我们实验性地评估了执行路径跟踪和可视化对微服务调试的有效性,并提出了多种可视化分析策略用于微服务调试。

在这项工作中,我们还通过引入更多的微服务(从24到41)和特性(例如,更多的语言,交互模式)扩展了我们早期的2页海报纸中介绍的基准系统。复制的故障案例已作为一个开源项目发布,可以很容易地集成到基准系统中。在复制包中可以找到我们的行业调查和实证研究的详细信息(以及我们的开源基准测试系统的源代码和复制的故障)。

本文的其余部分结构如下。第2节介绍了微服务架构的背景知识。第三部分描述了行业调查,包括过程和结果。第4节介绍了基准系统和22个重复的故障案例。第五部分介绍了基于重复故障案例的执行路径跟踪和可视化效果评估,并讨论了我们的观察和建议。第6节讨论了有效性的威胁。第7节回顾了相关工作。第8节总结了论文并概述了未来的工作。

2.   背景

微服务体系结构起源于面向服务的体系结构(SOA)的更广泛领域,其重点是小型轻量级微服务的组件化,敏捷和DevOps实践的应用,分散的数据管理以及微服务之间的治理。随着从单体架构迁移到微服务架构,架构复杂性已从基于代码的微服务转移到微服务的交互。不同微服务之间的交互必须使用网络通信来实现。微服务调用可以是同步的或异步的。由于停机的倍增影响,同步调用被认为是有害的。异步调用可以通过异步REST调用或使用消息队列来实现。前者提供了更好的性能,而后者则提供了更好的可靠性。由于用户请求通常涉及大量微服务调用,并且每个微服务都可能失败,因此需要相应地设计微服务,即,考虑微服务调用的可能失败。

微服务架构由一系列基础架构系统和技术的支持。诸如Spring Boot和Dubbo之类的微服务开发框架通过提供诸如REST客户端,数据库集成,外部化配置和缓存之类的通用功能,促进了微服务系统的开发。微服务系统广泛采用基于容器(例如Docker)的部署,以实现可移植性,灵活性,效率和速度。可以使用运行云基础架构框架(例如Spring Cloud,Mesos,Kubernetes和Docker Swarm),通过具有配置管理,服务发现,服务注册表,负载平衡的集群来组织和管理微服务容器。

微服务的独特特性给现有的调试技术带来了挑战。现有的调试技术是基于设置断点,手动检查中间程序状态以及进行性能分析而设计的。但是,这些技术对微服务无效。例如,由于高度的并发度,可能通过非常不同的执行来达到相同的断点,从而导致不同的中间程序状态。此外,微服务系统包含许多异步进程,这需要在不同进程之间跟踪多个断点。与调试单体系统相比,这种路径跟踪要困难得多。除了检查中间程序状态外,理解微服务如何相互交互以进行调试也同样重要。由于微服务的高度动态性,性能分析同样变得更加复杂。

此外,现有的故障定位技术对微服务无效。基于程序切片的故障定位通过识别与故障语句无关的程序语句并允许开发人员根据其余语句调查故障来进行。微服务的程序切片很复杂,因为我们必须考虑到不同进程之间的交互,才能对许多进程进行切片。基于频谱的故障定位使用信息来计算每个语句的可疑性,例如在通过测试执行或失败的测试执行中执行了多少次,并相应地对语句进行排名,以便开发人员可以专注于高度可疑的语句。没有证据表明此类技术可用于高度并行和动态的系统(例如微服务)。类似地,相关的故障定位技术主要设计用于顺序程序,例如基于统计的故障定位和基于机器学习的程序。

近年来,故障定位已扩展到并发程序和分布式系统。 两组工作都从记录线程(和节点)级执行信息开始,然后使用现有技术定位故障。将此类技术应用于微服务非常重要,因为微服务中的容器实例不断变化,导致日志检查困难和日志过于零散。

3.   行业调查

为了精确地了解行业需求,我们从行业调查开始,然后继续收集典型的故障案例以及对微服务调试的当前实践的了解。

3.1 参加者及程序

我们从本地技术社区中找到一组最初的调查候选人,他们曾在行业会议或在线帖子(例如文章,博客)中谈论微服务。这些候选人进一步推荐了更多的候选人(例如,他们的同事)。在这些候选人中,我们根据以下标准选择并邀请46位工程师进行面试。候选人必须具有6年以上行业软件开发经验和3年以上微服务开发经验。

在受邀工程师中,有16位接受了邀请。来自12家公司的16名参与者带来了他们正在或已经在使用的13种微服务系统的反馈。这些参与者广泛代表了不同类型的公司(即传统的IT公司,Internet公司和非IT公司),不同规模(50甚至1000多个微服务)的不同类型的微服务系统(Internet服务,企业系统),以及开发中的不同角色(技术角色和管理角色)。表1中列出了参与者和主题系统的信息,包括公司(C.),参与者(P.),主题系统,微服务数量(#S.)和参与者的位置。

在这12家公司中,C1,C6,C7,C8,C11和C12是领先的传统IT公司,其中C1和C8是《财富》500强公司;C3,C4,C5和C10是领先的互联网公司;C2和C9是非IT公司。13个主题系统可以分为两种类型。一种类型是通过互联网为消费者提供服务的互联网微服务,包括A3,A4,A5,A6,A10和A11。另一种类型是为公司员工提供服务的企业系统,包括A1,A2,A7,A8,A9,A12和A13。这些系统中的微服务数量从50到1000多个不等,其中大多数涉及约100-200个微服务。这16名参与者分别在各自的公司中担任不同的职务。在这些职位中,初级软件工程师,资深软件工程师,高级软件工程师和架构师是技术职位;经理是管理开发过程和项目进度的管理职位。

我们与每个参与者进行面对面的采访。首先要求参与者回想他/她最熟悉的微服务系统,并根据该系统提供他/她的后续反馈。参与者介绍了主题系统以及他/她在系统开发项目中所扮演的角色。然后,我们就以下问题采访并与参与者讨论:

l  您的公司为什么选择在该系统中应用微服务架构?系统是从现有的整体系统迁移还是作为新系统开发?

l  您的团队如何设计系统?例如,您的团队如何确定微服务的分区?

l  开发系统使用了哪些技术和编程语言?

l  您的团队在系统维护期间面临哪些挑战?

之后,要求参与者回忆他/她已处理的那些故障情况。对于每个故障案例,要求参与者描述故障并回答以下问题:

l  故障的症状是什么?如何重现?

l  故障的根本原因是什么?涉及多少个微服务?

l  调试过程是怎样的?调试花费了多少时间,使用了哪些技术?

面试后,如有必要,我们将通过电子邮件或电话与参与者进行后续沟通,以澄清一些细节。

3.2 一般实践

我们的调查显示,这些公司中的大多数,不仅是互联网公司,而且还包括传统的IT公司,都在一定程度上采用了微服务架构。独立开发和部署以及开发技术的多样性是采用微服务架构的主要原因。在13个接受调查的系统中,有6个是通过从现有的整体系统迁移而采用微服务架构的,而其余7个是使用微服务架构的相对较独立的业务的新项目。某些系统的迁移仍未完成:这些系统同时包含微服务和旧的整体模块。有关迁移的决定在很大程度上取决于其业务价值和工作量。

对第二个问题的反馈主要来自担任经理或架构师职位的参与者。5人中有4人选择对架构设计采用产品视角而非项目视角,并考虑基于产品业务模型的微服务分区。他们表示,该策略可确保不同微服务的稳定边界和责任。

在13个接受调查的系统中,有10个使用多种语言,例如Java,C++,C#,Ruby,Python和Node.js。其中一种系统(A6)使用超过5种语言。9位参与者指出,运行时验证和调试是主要挑战,它们严重依赖于微服务系统的运行时监视和路径跟踪。管理人员和架构师对使用运行时监视和路径跟踪来验证其系统是否符合微服务最佳实践和模式感兴趣,而开发人员对将其用于调试感兴趣。调试仍然是几乎所有参与者的主要挑战。他们通常花费数天甚至数周来分析和调试故障。

3.3 故障案例

总共16名参与者报告了22个故障案例,如表2所示。对于每种情况,该表均列出了其报告者,症状,根本原因以及用于定位根本原因的时间(以天为单位)。这些故障情况的详细说明(以及我们的开源基准测试系统的源代码和复制的故障)可以在我们的复制包中找到。请注意,在大多数情况下,开发人员需要几天的时间才能找到根本原因。根据故障的症状(功能性或非功能性)和根本原因(内部,相互作用或环境),可以将这些故障分为6个常见类别,如表3所示。

 

功能故障会引发错误或产生错误的结果,从而导致系统服务故障。非功能性故障会影响服务质量,例如性能和可靠性。从表3中可以看出,大多数故障是功能性的,导致不正确的结果(F1,F2,F8,F9,F10,F11,F12,F13,F14,F18,F19,F21,F22),运行时故障(F7,F15,F16)或无响应(F20);其中只有4个无法正常运行,从而导致服务不可靠(例如F3,F5)或响应时​​间过长(F4,F17)。

内部故障的根本原因在于单个微服务的内部实现。例如,F14是由微服务中实现的消费者价格指数(CPI)计算错误引起的内部故障。交互故障的根本原因在于多个微服务之间的交互。这些故障通常是由于微服务交互的缺失或不正确的协调引起的。例如,F1是由多个消息传递微服务的异步调用中缺少序列控制引起的;F12是由于另一个微服务的意外状态导致的微服务行为不正确引起的。环境故障的根本原因在于运行时基础结构的配置,这可能会影响单个微服务的实例或微服务集群的实例。例如,F3和F20分别是由Docker(集群级别)和JBoss(服务级别)的不正确配置引起的。这些故障可能会影响相关微服务的可用性,稳定性,性能甚至功能。

为了了解微服务系统中的故障特征,我们与每个参与者进行讨论,以确定所报告的故障情况是否特定于微服务体系结构。判据是在单体体系结构的系统中是否可能发生类似的故障情况。通过讨论,我们发现内部故障和服务级别环境配置故障在微服务系统和单体系统中都是常见的,而交互故障和集群级环境配置故障则是微服务系统特有的。

3.4 调试实践

基于调查,我们总结了微服务系统的现有调试过程,并确定了调试实践和技术的不同成熟度级别。我们还分析了所报告的故障案例的调试过程的有效性。

3.4.1        调试过程

我们的调查显示,所有参与者都依赖日志分析来进行故障分析和调试。他们的调试过程通常由描述故障的症状和可能的重现步骤的故障报告触发,并在修复故障后结束。调试过程通常包括以下7个步骤。

l  初步了解(IU)。开发人员根据故障报告对报告的故障有初步了解。他们还可以检查生产或测试环境中的日志以了解故障。根据了解,他们可能对根本原因有初步判断,或决定进一步重现故障以进行调试。

l  环境设置(ES)。开发人员建立了一个运行时环境以根据对故障的初步了解来重现故障。环境设置包括虚拟机的准备,相关微服务的部署以及相关微服务实例的配置。为了简化调试过程,开发人员通常会设置一个简化的环境,例如,它包括尽可能少的虚拟机和微服务。在某些情况下,开发人员可以直接使用产生故障的生产或测试环境进行调试,因此可以跳过此步骤。

l  失败再现(FR)。基于准备好的运行时环境,开发人员执行故障场景以重现故障。开发人员通常尝试使用不同的数据集来重现故障,以初步了解故障模式,这对于后续步骤很重要。

l  故障识别(FI)。开发人员从故障再现执行中识别故障症状。症状可能是开发人员在日志中发现的微服务实例的错误消息或微服务系统的异常行为(例如长时间没有响应)

l  故障范围(FS)。开发人员确定根本原因可能驻留的微服务系统的可疑位置,例如单个微服务的实现,环境配置或一组微服务的交互。

l  故障定位(FL)。开发人员根据识别出的可疑位置来定位故障的根本原因。对于每个可疑位置,开发人员都会确认它是否涉及导致故障的实际故障,并确定故障的精确位置。

l  故障修复(FF)。 开发人员修复发现的故障,并通过重新运行相关的测试用例来验证修复方法。

请注意,这些步骤并非总是顺序执行。如果后续步骤无法成功完成,则可能会重复某些步骤。例如,如果开发人员发现无法重现故障,则可以返回以重新设置环境。如果不需要某些步骤,则可以跳过。例如,如果一些有经验的开发人员可以根据生产或测试环境中的日志来定位故障,并通过其特殊的部分执行策略来验证故障的修复,则可以跳过环境设置和故障重现。

3.4.2        调试实践的成熟度

我们发现,针对这13个系统的调试实践和技术可以分为3个成熟度级别,如表4所示。

第一级是基本日志分析。在此级别上,开发人员分析系统产生的原始执行日志以查找故障。日志记录特定点系统的执行信息,包括时间,执行的方法,参数和变量的值,中间结果以及额外的上下文信息(例如执行线程)。基本日志分析遵循单体系统的调试实践,并且仅需要通用日志记录工具(例如Log4j)来捕获和收集执行日志。为了定位故障,开发人员手动检查了大量日志。在此级别上成功进行调试在很大程度上取决于开发人员在系统上的经验(例如,总体体系结构和易于出错的微服务)、类似的故障情况以及所使用的技术堆栈。

第二级是可视化日志分析。在此级别,执行日志的结构和可视化将用于故障定位。开发人员可以使用条件和正则表达式灵活地检索他们感兴趣的特定执行日志,并根据特定的调试策略对候选结果进行排序。所选的执行日志可以通过不同种类的统计图进行汇总和可视化。日志检索和可视化通常结合在一起,以允许开发人员以交互方式向上和向下浏览数据(执行日志)。例如,要定位导致微服务执行结果异常的故障,开发人员可以首先使用直方图来了解不同结果的范围和分布,然后选择特定的异常结果来检查相关的执行日志。为了支持可视日志分析,开发人员需要使用集中式日志记录系统来收集在不同节点中生成的执行日志,并将有关微服务及其实例的信息包括在执行日志中。此级别的日志分析高度依赖于日志收集,检索和可视化的工具。常用的工具集是ELK堆栈,即用于日志收集的Logstash,用于日志索引和检索的ElasticSearch和用于可视化的Kibana。

第三级是可视化路径跟踪分析。在此级别上,开发人员在路径可视化工具的支持下进一步分析收集的系统执行路径。路径跟踪是由方案(例如测试用例)的执行产生的,并且由用户请求跟踪段组成。用户请求跟踪段由共享相同用户请求ID(为每个用户请求创建)的日志组成。特别是,当用户请求进入系统的前端时,采用的跟踪框架将创建一个唯一的用户请求ID,该ID与请求一起传递给每个直接或间接调用的微服务。因此,为每个这样调用的微服务收集的日志记录了用户请求ID。开发人员可以使用可视化工具来分析用户请求的微服务调用链(从跟踪中提取),并识别微服务调用和执行的可疑范围。由于微服务可以并行调用多个微服务,因此可视化工具通常将微服务调用链组织为树形结构。例如,可视化工具可以垂直显示微服务调用的嵌套结构,并用彩色条水平显示每个微服务调用的持续时间。此级别的分析高度依赖于高级微服务执行路径跟踪和可视化工具。常用的工具集包括Dynatrace和Zipkin。我们的调查显示,大多数公司选择实施自己的跟踪和可视化工具,因为它们特定于微服务体系结构的实施技术。

与基本日志分析相比,可视日志分析为大多数类型的故障提供了更好的支持。灵活的日志检索功能可以快速过滤执行日志。微服务执行的可视化统计信息(例如变量值或方法执行计数)显示了微服务执行的模式。这些模式可以帮助定位可疑的微服务执行。例如,对于F22,开发人员可以根据统计信息轻松排除执行次数少于故障发生次数的方法。但是,定位与交互相关的故障通常需要开发人员在微服务调用链的上下文中了解微服务的执行。可视化路径分析通过将日志分析嵌入到跟踪上下文中进一步改善了可视化日志分析。例如,对于F1,开发人员可以将成功方案的路径与失败方案的路径进行比较,并根据特定微服务执行的不同顺序确定根本原因。

表2和表4显示,日志分析级别和故障之间通常不匹配。例如,系统A7仍处于基本日志分析级别,这无法帮助定位从该系统报告的故障F8。在这种情况下,开发人员通常需要手动调查大量执行日志和代码。它们通常从日志中触发故障的位置开始,然后向后检查日志以查找可疑的微服务并检查微服务的代码。

3.4.3        有效性分析

为了分析不同调试实践的有效性,我们收集了调试实践的成熟度以及22种故障案例中每个步骤所花费的时间。表5显示了结果,包括故障类型,故障案例(#MS)中涉及的微服务数量,支持的成熟度级别和调试的实际采用的成熟度级别,以及整个调试过程和各个步骤所花费的时间。最后一行显示了#MS的平均值以及整个调试过程和各个步骤所用时间的平均值。

请注意,在某些故障情况下,开发人员采用的调试实践的成熟度等级低于其团队所支持的等级。例如,对于F5,虽然开发人员配备了可视化路径跟踪分析,但是开发人员选择使用基本日志分析。此外,开发人员还可以结合不同级别的实践。例如,当他们采用可视化路径分析或可视化日志分析时,他们还可以使用基本日志分析来检查细节。

整个调试过程和各个步骤所花费的时间是从访谈过程中参与者的描述中获得的。参与者被要求按小时估算时间。为了验证他们的估计,要求参与者与他们的同事确认估计并检查其问题跟踪系统中的记录(例如,由错误分配和解决之间的时间表示的调试时间)。

平均而言,用于定位和修复故障的时间随故障中涉及的微服务数量而增加:一个微服务9.5小时,两个微服务20小时,三个微服务40小时,三个以上微服务48小时。对于某些故障情况(例如F6),总时间少于每个步骤所花费的时间总和。这通常是由于同时执行多个步骤引起的。例如,当在故障定位中确认故障的可疑位置时,开发人员可以同时进行故障范围界定,以识别更多可疑位置。

我们发现,对于交互故障,视觉日志分析和视觉轨迹分析的优势更加明显。在这些故障情况下,开发人员平均花费20、35、45小时分别采用可视化跟踪分析,可视化日志分析和基本日志分析。

通常,与其他步骤相比,最初的了解,故障范围划分,故障定位更加耗时,因为这些步骤需要对日志进行深入的了解和分析。同样在这些步骤中,可视日志/跟踪分析的优势更加明显。例如,使用可视化路径分析,可视化日志分析和基本日志分析时,初始理解的平均时间分别为3、7、21小时。在某些情况下(例如F9和F17-19),开发人员选择跳过环境设置和故障重现,因为他们可以轻松地从用户界面或异常中识别故障症状。在其他情况下(例如F17,F19,F21,F22),开发人员选择跳过故障识别和故障范围划分,因为他们可以根据故障症状和过去的经验来识别故障的潜在位置。

根据参与者的反馈,在拥有可视化日志/路径分析经验的13位参与者中,有11位认为可视化分析工具和实践非常有用。但是,这些工具和实践可以提供多少帮助,取决于错误的类型以及开发人员的经验,技能和偏好。

4.   基准系统和故障案例复制

我们的调查清楚地表明,微服务系统的故障分析和调试的现有实践可以大大改善。为了在这一领域进行研究,研究人员面临的困难之一是缺乏基准系统,这是由于建立现实的微服务系统非常复杂。因此,我们建立了一个基准系统:TrainTicket。我们的实证研究基于TrainTicket和调查中报告并在系统中复制的22个故障案例。该系统和复制的故障案例可以用作广泛的研究社区的有价值的基准,以进一步进行与实践相关的微服务故障分析和调试研究,甚至可以进行与微服务相关的其他广泛的实践相关研究。

TrainTicket提供典型的火车票预订功能,例如票查询,预订,付款,更改和用户通知。它是根据微服务设计原则设计的,涵盖了不同的交互模式,例如同步调用,异步调用和消息队列。该系统包含与业务逻辑相关的41个微服务(不计算所有数据库和基础架构微服务)。它使用四种编程语言:Java,Python,Node.js和Go。该系统的详细说明(以及我们的开源基准测试系统的源代码和复制的故障)可以在我们的复制包中找到。

我们复制了从行业调查中收集到的所有22个故障案例。通常,通过将故障机制从原始系统转移到基准系统来复制这些故障情况。下面,我们描述一些代表性故障案例的复制实现。其他故障情况的复制实现的说明可以在我们的复制包中找到。

F1是与异步任务相关的故障,即当我们在没有消息序列控制的情况下异步发送消息时。我们在TrainTicket的取消订单过程中复制此故障。在此过程中,将发送两个异步任务,这些任务没有其他序列控制。第一项任务应始终在第二项任务之前完成。但是,如果第一个任务被延迟并仅在第二个任务之后才完成,则该订单将达到异常状态,从而导致失败。

F3是由JVM和Docker的不正确配置引起的可靠性问题。JVM的最大内存配置与Docker群集的内存限制配置冲突。结果,Docker有时会终止JVM进程。我们在票证搜索过程中复制此故障。我们选择了此过程中涉及的一些微服务,并对其进行了修改以使其更加消耗资源。这些经过修订的微服务部署在配置冲突的Docker集群中,因此有时无法使用这些微服务。

F4是由于应用在大量微服务上的安全套接字层(SSL)配置不正确而导致的性能问题。结果是频繁地以细粒度卸载SSL,这会减慢相关微服务的执行速度。我们通过将错误的SSL配置应用于TrainTicket的每个微服务来复制此错误。然后,当用户请求服务(例如,机票预订)时,他/她将感觉到响应时间很长。

F5是由于线程池使用不当而引起的可靠性问题。微服务使用线程池来处理多种不同类型的服务请求。当线程池由于某种类型的服务请求的高负载而耗尽时,另一种类型的服务请求将由于超时而失败。我们在票务预订服务中复制此故障,该服务同时为票务搜索过程和票务预订过程提供服务。当票证搜索的负载很高时,该服务的线程池将被耗尽,并且由于超时,对该服务的票证预订请求将失败。

F8是由调用链上传递的参数缺失或不正确引起的。我们在订单取消过程中复制此故障。当VIP用户尝试取消票单时,保存在Redis(内存数据存储)中的登录令牌不会传递给某些需要该令牌的微服务。此故障会导致用户意外获得较低的机票退款率。

F10是由微服务的意外输出引起的,该微服务在业务处理的特殊情况下使用。我们在票务预订过程中复制了此错误。在票务订购服务中,我们实现了两个API,分别用于常规票务订购和某些特殊车站的票务订购。特殊机票订购的API有时会返回未正确处理的意外输出,从而使机票预订过程失败。

F11是由于缺少序列控制导致的数据异步更新中发生的故障。当物料清单(BOM)树以意外顺序更新时,生成的树不正确。但是,当用户打开产品BOM服务的“严格模式”时,当BOM树包含一些负数时,将重新生成结果树,从而生成正确的树。我们在订单取消过程中复制此故障,该过程包括两个微服务(支付服务和取消服务),这些服务在数据库中异步设置相同的值。由于缺少序列控制,因此两个微服务可能会以错误的顺序设置该值,从而导致错误的值。但是,如果用户在订购服务上打开“严格订购”模式,则最终将纠正不正确的值。

F12由处于特殊状态的微服务的意外输出引起。我们在票务预订过程中复制了此错误。我们为票务预订服务实例引入状态admDepStation / admDesStation,以指示管理员正在检查票证的出发/目的地站点。如果没有管理员检查情况,则相应的票务预订服务实例将处于无状态。如果票务预订请求的出发/目的地站是admDepStation / admDesStation,并且同一预订请求线程两次或多次访问票务预订服务(包括有状态实例和无状态实例),则该请求将被拒绝,并产生意外的输出,并且票务预订过程返回错误。

对于上述每个故障,我们都会在故障案例存储库中为其复制创建一个开发分支。使用该信息库的研究人员可以轻松地混合并匹配不同的故障,以生成包含多个故障的TrainTicket的故障版本。

5.   实证研究

我们对TrainTicket系统和重复故障案例的实证研究包括两个部分。在第一部分中,我们研究了针对故障案例的现有行业调试实践的有效性。在第二部分中,我们基于用于分布式系统的最新调试可视化工具,开发了微服务执行路径跟踪工具和两种用于故障定位的跟踪可视化策略,并研究了它是否可以提高调试交互故障的有效性。由6名熟悉TrainTicket并在微服务开发方面具有类似经验的研究生作为独立进行调试的开发人员。对于每种故障情况,开发人员都根据给定的故障报告来定位和修复故障,并且使用不同实践进行调试的开发人员也有所不同。为了提供公平的比较,我们为每种故障情况和每种做法随机选择一名开发人员,以允许开发人员针对不同的故障情况使用不同的做法。开发人员遵循3.4.1节中介绍的一般过程进行调试。对于任何步骤,如果开发人员无法在两个小时内完成,他们可以选择放弃,并且该步骤和整个过程都会失败。

5.1 使用行业调试实践进行调试

在本部分研究中,我们分别通过定性分析和定量分析研究了三个成熟度级别的调试实践的有效性。对于每种故障情况,选择三个开发人员以不同成熟度级别的实践进行调试。为不同成熟度级别提供的工具如下。

l  基本日志分析。开发人员使用命令行工具来获取和分析日志。

l  可视日志分析。开发人员使用ELK堆栈,即Logstash进行日志收集,ElasticSearch进行日志索引和检索以及Kibana进行可视化。

l  可视化路径分析。开发人员同时使用ELK堆栈和Zipkin进行调试。

5.1.1        定性分析

我们根据F8的调试过程定性比较不同级别的实践,如图1所示。

图1(a)展示了基本日志分析的快照,该快照显示了从运行食品服务微服务的容器中捕获的日志。开发人员在红色框中识别出可疑的日志片段,发现食品退款率为68%,低于食品订购的预定义VIP退款率。因此,他们可以将食品退款率的计算视为潜在的故障位置。基本日志分析的不足是缺少微服务调用的上下文,这使得开发人员很难在用户请求和调用链的上下文中分析和理解日志。

图1(b)展示了可视化日志分析的快照。它显示了不同虚拟机中两个相关微服务(食品服务和寄售服务)实例的平均退款率直方图以及相应的日志。这两项服务的退款都包含在机票退款中。由于故障现象是门票退款率低,因此开发人员选择最低的条,以显示VM3中的平均食物退款率(请参见图1(b)中的红色框)来检查日志。从日志中,开发人员发现最低的食物退款率是65%,因此将食物退款率的计算视为潜在的故障位置。与基本日志分析相比,可视日志分析提供了变量和质量属性(例如响应时间)的汇总统计信息,从而可以帮助开发人员识别可疑的微服务和实例。但是,它缺少用户请求和调用链的上下文,因此无法支持微服务交互的分析。

图1(c)展示了可视化痕迹分析的快照。它显示了订单取消过程的整个轨迹,包括微服务的嵌套调用以及每次调用的消耗时间。开发人员发现,票证取消过程不仅调用食品服务和寄售服务,还调用配置服务和路由服务。然后他们进一步分析配置服务的日志,发现票证取消过程使用可疑的一般退款率(最低情况下为36%)来计算最终退款率。因此,他们将配置服务中一般退款率的计算视为潜在的故障位置。此故障定位比基本日志分析和可视日志分析支持的定位更加精确。

与可视化日志分析相比,可视化路径跟踪分析支持在用户请求和调用链的上下文中理解微服务执行。

5.1.2        定量分析

研究结果如表6所示,包括整个调试过程和每个步骤所用的时间。标记“-”表示开发人员跳过该步骤。如果跳过所有步骤,则意味着可以通过较低级别的实践(例如基本日志分析)轻松识别并修复故障,因此无需更高级别的实践。标记为“失败”表示开发人员无法完成该步骤。如果调试过程的某个步骤失败,则整个过程也会失败。

在所有三个级别的行业实践中,开发人员在F3和F4中均失败。它们都是非功能性环境故障。对于F9,F19,F21,F22,开发人员可以通过基本的日志分析轻松地定位并修复故障。所有这些都是内部故障。对于其他故障,通过使用更高级别的调试实践(从基本日志,可视日志到可视化路径跟踪分析),通常存在减少调试时间的趋势。在这些故障情况下,交互故障是从更高级别的调试实践中受益最大的故障。

与行业调查类似,与其他步骤相比,最初的了解,故障范围,故障定位更耗时,并且有时会跳过环境设置和故障重现。环境设置和故障再现所用的时间随所采用的调试实践而异。根据开发人员的反馈,他们经常尝试根据初步了解进行最简单的故障重现,因此初步了解的准确性会影响环境设置和故障重现所用的时间。

5.2 通过改进的路径跟踪可视化进行调试

从上面的内容,我们观察到路径跟踪和可视化可以潜在地帮助微服务系统的故障分析和调试。因此,在本部分研究中,为了更好地支持微服务系统的故障分析和调试,我们研究了最新的分布式系统调试技术对微服务系统调试的有效性。

5.2.1        路径追踪和可视化方法

ShiViz是用于分布式系统的最先进的调试可视化工具。它将分布式系统执行可视化为交互式时空图,以明确捕获系统中事件的分布式顺序。ShiViz通过突出显示它们的差异来支持两条迹线的成对比较。它通过名称和描述比较了两个路径跟踪中的分布式系统节点和事件,并突出显示了另一个路径跟踪中未出现的节点或事件(在一个跟踪中)。ShiViz支持选择一路径的一部分进行比较。例如,我们可以根据请求ID选择一个用户请求路径跟踪段,即特定用户请求的事件。

图2展示了ShiViz进行的路径可视化的示例,其中显示了节点(顶部的彩色框),节点时间线(垂直线),事件(时间线上的圆圈)以及事件之间的局部顺序(连接事件的边)。左侧的菱形(事件)突出显示了两条迹线之间的差异,我们也可以单击以查看菱形的详细信息。

通过将微服务单元作为分布式节点进行处理,我们将执行信息(例如,服务名称,用户请求ID和调用的方法)添加到节点和事件的名称和描述中,此成对比较可用于在微服务系统调试中查找可疑节点和事件。通过将路径跟踪日志转换为ShiViz的日志格式,我们可以利用ShiViz来可视化微服务的路径跟踪。但是,可视化微服务跟踪的一个基本问题是如何将微服务单元映射到节点。微服务实例在容器上运行,并且可以与其容器一起动态创建或销毁。而且,分配给处理微服务调用的实例是不确定的。因此,微服务实例(容器)不能视为路径跟踪可视化中的节点。因此,我们提出了以下两种微服务跟踪的可视化策略。

l  微服务作为节点(服务级别分析)。同一微服务的所有实例都被视为一个节点。因此,在同一微服务的不同实例的事件被聚合到同一节点。

l  微服务状态作为节点(状态级别分析)。具有相同状态(基于预定义的状态变量或表达式确定)的相同微服务的所有实例都被视为一个节点。因此,在同一微服务的不同实例以及在相同状态期间的事件将聚集到同一节点。该技术取决于每个微服务的预定义状态变量或表达式。

执行微服务系统的场景(例如测试用例)产生的跟踪可能包含许多用户请求(例如,通过单击网页上的按钮触发的票证查询请求)。在跟踪中,每个用户请求产生的用户请求跟踪段包括一系列微服务调用。此外,每个微服务调用可能涉及在不同微服务实例上发生的多个执行事件,例如发送/接收调用请求或回调。因此,执行跟踪工具需要记录所有执行事件,并将用户请求ID(简称为请求ID)和微服务调用ID(简称为ID)附加到每个日志中。我们的工具是用Java实现的。对于REST调用,我们使用servlet过滤器和拦截器将调用者的路径信息注入到HTTPRequest对象的http标头中。注入的信息包括请求ID,调用ID,微服务名称,实例ID,IP地址,端口号,所调用的微服务的类名称和方法名称和调用者。此类信息与http请求一起发送给被调用方。对于消息队列,我们​​使用消息通道拦截器来注入和捕获交互队列数据。基于此类路径信息,每个微服务实例都会记录路径日志,然后由我们的中央日志记录系统收集这些日志。

基于这两种可视化策略,我们利用ShiViz通过成对比较路径来诊断微服务故障。这一特性使ShiViz优于以前的微服务路径/可视化工具,例如ELK stack,Zipkin。

5.2.2        调试方法

基于路径跟踪工具和两种可视化策略,我们定义了一种调试方法,如图3所示,用于基于分布式系统常规调试实践的实证研究。该过程的基本原理是基于这样一个假设,即故障路径跟踪的发现错误的部分与成功跟踪中的相应部分不同,并且与另一个故障跟踪共享。

对于每个故障,我们收集执行同一场景(具有不同的参数值)产生的一组跟踪,包括成功跟踪和失败跟踪。我们选择一个成功跟踪TraceS和两个失败跟踪TraceF1和TraceF2进行比较。我们首先根据用户请求比较TraceS和TraceF1。例如,票务预订场景包括一系列用户请求,例如票务查询,火车选择和乘客选择,并且分别比较了两条路径中每个请求的事件。为了简化用户请求的选择,我们在日志中为每个请求ID附加了可读标签(例如“票证查询”)。基于比较,我们可以获得一组差异范围DR,每个差异范围是两个路径之间不同的多个连续事件。然后,我们根据用户请求在TraceF1和TraceF2之间进行比较,以确认两个路径中共享的DR范围。DR中已确认的范围被标识为故障显示范围。

这项研究的目的是调查基于路径的调试是否可以从改进的路径跟踪和可视化中受益。因此,我们根据以下两个标准从22个故障案例中选择12个故障案例进行研究。首先,它们是交互或环境故障,因为内部故障无法从跟踪分析中受益。其次,通过可视化路径分析,它们的调试时间超过1小时(请参见表6)。选定的故障情况为:F1,F2,F3,F4,F5,F7,F8,F10,F11,F12,F13,F16。对于每种故障情况,都会选择不使用行业调试实践来调试故障的开发人员来定位和修复故障。

5.2.3        定性分析

通过改进的路径可视化,不同的调试步骤可以获得的好处是不同的。为了初步了解,开发人员可以对成功跟踪和失败跟踪之间的总体差异有所印象,包括差异范围的数量和大小。一些开发人员甚至可以在初步了解的情况下直接识别可疑的故障位置。通过更准确地初步了解故障,环境设置,故障再现和故障识别可以间接从分析中受益。通过确定差异范围,故障范围和故障定位可以直接从分析中受益。通过故障修复的验证,故障修复可以间接从分析中受益。

图4显示了F10中错误的微服务调用的服务级别分析示例,该错误是由于对微服务的API之一的意外输出的不正确处理引起的。开发人员可以在红色框中看到两个区别(菱形),这表明所调用的API是不同的(尽管所调用的微服务是相同的)。由于故障路径比较中的相应范围没有差异,因此他们可以将该范围标识为潜在故障位置。

图5显示了F1中交互序列错误的服务级别分析示例,该错误是由于缺少异步调用协调引起的。根据事件的结构,开发人员可以在成功跟踪和失败跟踪中识别出两对相应的范围,分别显示为红色框和绿色框。他们可以发现两条路径中两个范围的顺序不同。由于订单在故障跟踪的比较中没有差异,因此可以将差异识别为潜在的故障位置。

图6显示了F12的服务和状态级别调试的示例。当进行如图6(a)所示的服务级别分析时,失败路径和成功路径之间没有区别。然后,开发人员选择使用状态级别分析,通过引入状态变量或表达式来完善路径的比较。基于对系统的了解,开发人员选择尝试票务服务下的两个状态变量:管理员检查站,指示管理员正在检查票证的出发/目的地站;以及订单处理线程池,指示是否正在检查票证池的限制未达到,未达到或超过(0、1或2)。由于管理员检查站具有20多个不同的值,因此开发人员选择使用状态表达式代替状态变量,例如,使用国家/地区信息:GetRegion(管理员检查站)。然后,开发人员将获得状态级别的分析结果,如图6(b)所示。可以看出,票务订购服务的节点已用组合状态(“ region5” / 0和“ region3” / 1)进行注释,从而确定了故障跟踪和成功跟踪之间的差异(节点和事件)并突出显示为菱形(在红色框中)。开发人员进一步检查了两个故障路径之间的比较,如图6(c)所示,该比较将具有相同管理状态(“ region3”)和不同线程池状态(2和1)的票单服务进行了比较。这两个比较提供了初步的证据,表明票务服务的管理员检查“region3”的状态与故障有关,并且图6(b)中突出显示的范围是候选故障显示范围。

 

必要时,开发人员可以引入更多状态变量/表达式进行比较,但要付出在可视化路径跟踪中拥有更多节点的代价。开发人员可以逐步调整策略,并尝试状态变量/表达式的不同组合。启发式可以应用于识别这样的组合。例如,期望的状态变量/表达式很可能是根据静态变量,单例成员变量或临时存储(例如Redis)中的键值构建的。

我们发现,所有成功的分析都是基于以下四种比较失败路径和成功路径的策略。

T1(单事件差异)。故障显示范围是单个事件,并且区别仅在于事件的描述(例如,被调用的方法)。

T2(单范围差异)。故障显示范围涉及节点之间的不同交互序列。

T3(多范围差异)。多个故障显示范围的执行顺序是不同的。

T4(多请求差异)。多个用户请求的执行顺序是不同的。

在这些策略中,T1不涉及节点交互顺序的差异,而其他三个策略则涉及。表7中也显示了用于分析每种故障情况的策略。可以看出,由于故障可能涉及不同级别的多个故障显示范围,因此可以将策略组合在一起以进行调试以定位故障。通过在较大范围内分析路径差异,调试的难度从T1增加到T4。

T4相对难以使用,因为它涉及不同用户请求之间的复杂交互。F2是必须使用T4的示例。由于微服务系统中异步交互的广泛使用,用户请求的处理顺序并不总是与其接收顺序相对应。如果不同用户请求之间存在交互,则很可能由于处理用户请求的协调错误而引入故障。F2是这种情况的一个示例。由于路径分析涉及多个用户请求中的大量事件,并且不同请求的事件相互交错,因此,除非成功和失败路径之间的差异反映在单个请求的路径比较中,否则无法基于现有的可视化技术对F2进行有效分析。对于F2,开发人员花费大量时间来寻找根本原因。但是对于F13,由于与F2相比,路径分析所涉及的多个用户请求中的事件数量要少得多,并且ShiViz上不同请求的事件可以轻松区分,因此可以有效地分析F13,并且消耗的时间更少。

5.2.4        定量分析

表7中显示了使用改进的路径可视化进行调试的时间分析结果。在12个故障案例中,开发人员在2个案例(F3和F4)中失败了,而他们在可视化路径分析中也失败了。对于F16,开发人员可以成功,但要比可视化路径分析花费更多的时间。这三种情况都是环境故障(F3和F4不起作用,F16起作用);这样的结果表明调试此类故障无法从路径分析中受益。

在所有其他9种故障情况下,开发人员可以将调试时间从3.23小时减少到2.14小时,从而提高了调试效率。请注意,这9个故障案例都是交互故障。对于这些故障,故障定位,初步了解,故障重现是从分析中受益最大的三个步骤。与可视化路径分析相比,用于这些步骤的时间分别减少了49%,28%和24%。

表7还显示了开发人员针对12种故障情况中的每一种的详细分析过程,包括使用的可视化策略,节点数(#N.),事件数(#E.),用户请求数(#UR.),在每个分析中确定的故障显示范围的数量(#FR.),在每个分析中的故障显示范围的事件数量(#FE.)和在每个分析中的命中(即,成功地确定至少一个真正的故障显示范围的分析,“Y”表示已成功识别,“N”表示失败)。标记“-”表示开发人员无法识别范围或事件。结果表明,每次调试都结合了成功和失败的路径,涉及大约7-22个节点(代表服务或服务状态)以及成百上千个事件。这些事件属于2-7个用户请求,并且分别比较每个用户请求的路径。

每次成功的分析都会确定带有数十个事件的几个故障显示范围。对于某些故障情况(F1,F2,F7,F8,F10和F13),服务级别分析可以有效地确定故障显示范围(命中为“ Y”)。其他一些故障情况(F5,F11和F12)需要服务状态级别分析,以识别故障显示范围。对于F12,两位开发人员都成功地确定了问题状态之一。

也有不成功的情况(F3,F4),表明开发人员未能找到至少一个故障揭示范围。主要原因是这两种情况都是环境故障,我们的调试方法未充分支持它们。

5.3 发现

我们的研究表明,除了那些由环境设置引起的故障案例之外,大多数故障案例都可以从路径可视化中受益,尤其是那些与微服务交互相关的案例。通过将微服务或微服务状态视为节点,我们可以使用最新的分布式系统调试可视化工具来进一步提高微服务调试的效率。状态级路径跟踪和可视化的困难主要在于微服务状态的定义。由于微服务系统可能具有大量的微服务和状态变量/表达式,因此它高度依赖于开发人员的经验,以通过识别一些有助于揭示故障的关键状态来实现有效而高效的故障分析。

路径可视化的挑战在于大量的节点和事件。大型工业微服务系统在一个路径中具有成百上千个微服务以及成千上万个事件。如此众多的节点和事件会使可视化分析不可行。这个问题可以从两个方面缓解。首先,需要更好的路径可视化技术,例如放大(缩小)节点(事件)聚类,以使开发人员能够专注于可疑范围。例如,节点/事件聚类可以将聚合的节点和事件自适应地分组在一起,从而通过逐步公开信息来减少要检查的节点和事件的数量。其次,可以将故障定位技术(例如基于频谱的故障定位和增量调试)与可视化分析相结合,以进行微服务调试。一方面,该组合可以通过对微服务调用应用统计错误定位来建议跟踪中的可疑范围,另一方面,该组合可以提供特定微服务内代码级别故障定位(例如代码块)的结果。

鉴于微服务交互的规模和基础架构的动态性导致了极大的复杂性,我们认为微服务的调试需要以数据驱动的方式来支持。例如,一种方法是将人类的专业知识与机器智能相结合,以进行引导的视觉探索和路径比较。支持工具可以充分利用运行时监视和历史分析生成的大量数据,并在可视化探索和比较路径时提出关键的建议和指导。例如,这些工具可以在路径和敏感状态变量中建议可疑范围,从而根据概率数据分析来区分成功和失败的轨迹,或者推荐具有相似轨迹模式的历史故障案例。基于这些建议和指导,开发人员可以深入研究路径的可能部分,或添加相关的状态变量以进行路径比较和可视化。这些动作又被工具收集并用作反馈,以改进进一步的建议和指导。

6.   对有效性的威胁

我们研究的外部有效性的一个普遍威胁在于参与者和错误案例的有限。从这些参与者那里学到的行业经验可能并不代表具有不同特征的其他公司或微服务系统。从行业参与者那里收集的故障案例可能不会涵盖更复杂的故障或其他不同的故障类型。行业调查内部有效性的主要威胁在于从参与者那里收集的信息的准确性(例如,每个调试步骤的时间)。由于此类信息并非完全基于精确的历史记录,因此某些信息可能不准确。

实证研究对外部有效性的威胁主要在于基准体系的代表性。尽管是我们所知的最大,最复杂的开源微服务系统,但该系统目前比大多数被调查的行业系统更小,更复杂(例如,异构程度更低)。因此,从研究中获得的一些调试经验可能不适用于大型行业系统。

对实证研究的内部有效性存在三大威胁。第一个是根据我们的理解执行故障案例。理解可能不准确,并且某些故障在不同系统中的复制可能无法完全捕获故障案例的基本特征。第二个问题在于运行时环境的不确定性,例如访问负载和网络流量。在不同的环境设置下,某些故障的行为可能有所不同,因此需要不同的调试策略。第三点在于参与研究的开发人员的经验和技能的差异。这些差异也可能导致调试时间和采用不同实践的结果有所不同。

7.   相关工作

一些研究人员使用系统映射研究和文献综述来回顾微服务研究的发展和现状。Francesco等人从三个角度对微服务架构的最新技术现状进行了系统的映射研究:发布趋势,研究重点和行业采用的潜力。他们的结论之一是,关于微服务架构的研究仍处于初期阶段,行业和学术作者的均衡参与是有希望的。Alshuqayran等人对微服务体系结构进行了系统的映射研究,重点研究了微服务系统的体系结构挑战,用于表示它们的体系结构图以及所涉及的质量要求。Dragoni等人回顾从对象、服务到微服务的开发历史,介绍当前的技术水平,并提出一些未解决的问题和未来的挑战。Aderaldo等人提出了用于软件体系结构研究的候选微服务基准系统的一组初始要求。他们根据这些要求评估了五个开源微服务系统,结果表明它们中没有一个成熟到足以用作社区范围的研究基准。我们的开源基准测试系统为填补此类空缺提供了一个有前途的候选人。我们的行业调查很好地补充了这些先前的系统的映射研究和文献综述。

已经有一些关于调试并发程序和分布式系统的研究。Asadollah等人在2005年至2014年这十年间对并发和多核软件的调试进行了系统的映射研究。Bailis等人对分布式系统的最新调试技术进行了调查,得出的结论是,分布式调试的最新技术系统仍处于起步阶段。Giraldeau等人提出了一种使用调度,网络和中断事件来可视化分布式系统执行的技术。Aguerre等人介绍了一个包含分布式调试器的仿真和可视化平台。Beschastnikh等人讨论了分布式系统的主要功能和调试挑战,并提出了一个名为ShiViz的调试可视化工具,我们的验证研究对其进行了研究和扩展。与之前的研究相比,我们的工作是第一个专注于对微服务系统的调试支持的工作。

8.   结论

在这项工作中,我们进行了一次行业调查,包含对微服务系统的典型故障进行分析、当前的调试行业实践以及开发人员面临的挑战。根据调查结果,我们开发了一个中等规模的基准微服务系统(在我们所知范围内是最大,最复杂的开源微服务系统),并基于该系统从行业案例中复制了22个代表性故障案例。这些复制的故障随后已用作我们对微服务调试进行实证研究的基础。研究结果表明,通过使用适当的路径跟踪和可视化技术或策略,路径和可视化分析可以帮助调试以定位涉及微服务交互的各种故障。我们从研究中发现的结果还表明,需要更智能的路径分析和可视化,例如,通过结合路径可视化和改进的故障定位技术,并采用数据驱动和基于学习的建议来进行引导的可视化探索和路径比较。

行业微服务系统通常很大且很复杂。例如,工业系统在微服务交互中高度异构,并且不仅可以使用REST调用和消息队列,还可以使用远程过程调用和套接字通信。此外,工业系统正在高度复杂的基础结构上运行,例如自动扩展微服务集群和服务网格(用于服务到服务通信的专用基础结构层)。这种复杂性和异构性对执行路径跟踪和可视化提出了额外的挑战。我们未来的工作计划进一步扩展我们的基准系统,以反映工业微服务系统的更多特征,并探索有效的路径可视化技术以及故障定位技术(例如基于频谱的故障定位和增量调试)的组合,以进行微服务调试。此外,我们计划探索一种与技术无关的方式,以通过Linkerd和Istio等服务网格工具在每次服务调用时注入路径信息。

致谢

这项工作得到了国家重点研究发展计划的资助,批准号为2018YFB1004803。陶谢的工作得到了美国国家科学基金会的部分资助,批准号为CNS-1513939,CNS-1564274和CCF-1816615。

posted @ 2021-04-29 23:51  北漂的尘埃  阅读(290)  评论(0编辑  收藏  举报