利用机器学习保证个体微服务的容量安全

0
利用机器学习保证个体微服务的容量安全

Uber的可靠性工程团队构建工具、库和基础设施,使工程师能够大规模可靠地操作我们的数千个微服务。本质上,可靠性工程归根结底,要积极防止影响平均故障间隔时间(MTBF)。

随着Uber全球移动平台的发展,我们的全球规模和复杂的微服务呼叫模式网络使得单个服务的容量需求难以预测。当我们无法预测服务级别的容量需求时,就会发生与容量相关的中断。考虑到我们运营的实时性,与容量相关的停机(在功能级别上影响微服务,而不是直接影响用户体验)构成了Uber整体停机的很大一部分。

为了帮助防止这些中断,我们的可靠性工程师遵循一个概念称为安全能力换句话说,支持历史峰值或来自单个数据中心的并发骑手的90天预测,而不会造成严重的CPU、内存和一般的资源短缺。在地图可靠性工程团队中,我们建立了内部的机器学习工具预测核心服务指标- - - - - -每秒请求数、延迟和CPU使用率- - - - - -提供这些指标在一周或一个月的过程中如何变化的想法。使用这些预测,团队可以执行准确的容量安全测试,捕捉每个微服务的细微差别。

在本文中,我们定义了Uber的容量安全,并讨论了我们如何利用机器学习来设计我们的容量安全预测工具,特别强调计算可靠性评分的质量,这是一种度量方法,允许负载测试套件以编程的方式决定是否依赖预测。

Uber的容量安全

作为容量安全措施的一部分,每个微服务都必须正确配置,这样它就不会在每个数据中心同时停机。配置不足会导致容量不足,而过度配置会给下游或上游服务带来与网络相关的挑战(例如高于所需连接数)。

过去,我们的可靠性工程团队进行了全平台的演练,以确保核心起下钻-流服务的产能安全。当指定的模拟起下钻量到达平台时,工程师会监测核心指标。除了监视靠近平台入口点的微服务外,团队还对了解初始负载和后续调用模式如何影响下游微服务的性能感兴趣。

虽然这种平台范围的方法解决了容量安全这一更广泛的问题,但它也引入了许多挑战,包括需要确保保真度和无缝的开发人员体验。“忠实”的概念是,所有关键服务都以与自然流量相同的方式进行测试。顶级微服务经过了彻底的测试,但是像地图系统和支付服务这样的后端深度微服务没有得到类似的覆盖。此外,为了提供受控的测试环境,平台范围的压力测试锁定了整个部署系统。不出所料,这对开发人员的体验产生了负面影响,因为它阻碍了正在进行的构建和部署。

为了解决这些问题,可靠性工程师提出了一个本地化的、自动化的、特定于服务的容量安全测试,构建在现有工具之上,可以独立执行。这种方法比较困难,因为必须考虑到每个服务的复杂性、模式和使用。此外,为了通过这个测试,我们构建了内部工具来预测核心服务指标,从而为我们提供了一个更好的想法,即我们的服务是否将满足容量安全需求。

设计一个支持机器学习的架构

图1:Maps Reliability Engineering预测系统的体系结构和设计,结合了数据收集和存储和数据预测,促进了更大的微服务可靠性。

在较高的级别上,Uber生产中的每个服务都被检测出指标,其中一些是与资源和能力相关的。这些指标存储在M3并可通过API查询。我们的预测系统使用一个服务查询配置文件来确定哪些服务需要预测。有兴趣使用该系统的内部开发人员可以通过指定他们的服务名称、核心指标(例如,每秒请求数)和每小时/每天的预测间隔在他们的服务上。

像任何机器学习任务一样,预测需要大量的训练数据才能相当准确。为了做出准确的预测,必须有足够的数据捕捉时间序列的趋势和季节模式。我们的服务利用一个收集器在M3上执行范围查询,并将数据存储在一个抽象的存储层中。

当服务开始进行预测时,将从存储层检索其相应的训练数据。然后,数据经过多级预处理,以去除异常事件。在预测步骤中,使用各种统计技术来获得准确的预测。最后,对预测进行验证,以确定模型在训练数据上的表现如何。

预测系统可以配置为在给定的时间块内以周期性间隔运行。这使系统能够动态地适应服务级别的更改和事件。例如,如果一个服务开始经历异常高的请求量,系统将考虑这个新模式并相应地改变预测。

在每个采集和预测周期结束后,结果被存储在存储层。如果预测由于上述事件而发生更改,则使用优先级队列将过时的预测覆盖为更新的预测。最后,有兴趣将预测用于测试目的的服务所有者可以通过API查询数据。

数据采集

我们使用的数据(如关于CPU和内存使用情况的信息)来自可靠的来源(如服务器日志、事件日志和数据中心报告),这为我们提供了用于预测的健壮训练集。考虑到预测水平与训练数据集的大小直接相关,我们决定不限制收集的数据点的数量。然而,M3的默认保留策略使我们无法获得足够的数据进行预测。在大多数情况下,时间序列数据的价值随着时间的推移而减少,所以通常情况下,丢弃较老的数据是经济的。然而,这些“陈旧的”数据在预测系统中扮演着重要的角色,因为它使模型能够预测越来越远的未来。毕竟,这些模型只能通过包含历史趋势和季节的数据集来捕捉长期趋势和季节性模式。

图2:预测范围大约是训练数据集大小的25%。因此,训练数据集中包含的点越多,可以预测的点就越多。

因为对M3的每个范围查询只返回有限的时间序列数据点,所以我们进行连续查询来检索整个数据集,以容纳我们的大量服务器,如上面的图2所示。然而,由于时间序列是周期性收集的,我们经常注意到在每个区间的开始和结束的无效数据点。这是由于M3设计决策在时间序列数据传入时预先聚合它,然后存储输出以供将来查询。当收集间隔与聚合间隔不对齐时,间隔边就没有有效的数据点。为了解决这个问题,我们在每个收集间隔的开始和结束处引入了一个缓冲周期,当将来自连续收集的数据拼接在一起时,这个缓冲周期将被删除。这个特性使我们能够覆盖无效的数据点,同时保持系统与M3的聚合策略兼容。

下一步是持久化收集到的数据,以构建一个训练数据集。超级的M3团队意识到对更长的保留时间的日益增长的需求,并开始为用户提供为单个时间序列数据配置保留和聚合策略的选项。

最初,我们将时间序列数据存储在本地,以方便快速原型。我们选择BoltDB,一个开源的嵌入式键值存储。BoltDB是一个很好的原型选择,但对于生产来说还不够,因为时间序列数据不能在预测系统的多个实例之间共享。此外,由于数据是嵌入的,所以每次发生新的部署时,数据都会被擦除。结果,我们转到了DOSA医生这是我们在Apache Cassandra上构建的一个开源存储解决方案。DOSA适合我们的需求,因为我们主要是基于时间戳执行范围查询,不需要执行复杂的关系查询。DOSA还通过在实例之间提供一致的视图和跨部署持久化解决了BoltDB的问题。

除了保持持久性,我们还需要保持预测系统的高可用性,因为它可能在获取过程中遇到各种各样的故障。为了确保容错能力,我们在多个数据中心运行预测系统的多个实例,以确保在任何给定时间至少有一个实例在运行。在此场景中,当发生并发收集时,数据一致性也是一个问题。由于M3预先聚合时间序列数据,实例总是查询相同的数据,因此不需要做额外的工作来保持数据一致性。

数据预处理

在我们的系统预测时间序列数据之前,对历史数据集进行预处理,以去除可能影响预测的异常值、异常值和其他不规则变化。特别是,从任何服务检索的时间序列数据可能包含发生数据中心故障的时间间隔。我们当前的平台级容量安全流程要求发生数据中心故障转移。但是,当“失败”数据中心中的系统显示异常行为时,必须从数据集中删除这些时间间隔。

预处理时间序列数据的第一步是识别和删除与数据中心故障转移对应的时间间隔。这些间隔很容易直观地检测到,因为来自一个数据中心的流量接近零,而另一个数据中心的流量接近其原始负载的两倍。然而,自动检测数据中心故障转移并不是一项简单的任务。

图3:在这个假设的场景中,在故障转移期间,数据中心DC 2中的流量逐渐趋于零,而DC 1吸收过去在DC 2中的流量。几个小时后,两个数据中心都恢复正常运行。

由于故障转移相对于数据集的其余部分具有非常特定的特征,因此机器学习可以用来将这些特征作为特征。与传统的分类任务不同,我们的能力训练目标是对时间序列中的异常区间进行分类,使训练和预测阶段根据训练条件而不同。

培训阶段包括:

  • 建筑物的摇窗k数据集的数据点
  • 根据整理的数据为每个滚动窗口标记“故障转移”或“无故障转移”
  • 从每个故障转移窗口提取大量时间序列特征

预测阶段包括:

  • 建筑物的摇窗k数据集的数据点
  • 使用训练过的模型将每个滚动窗口分类为“故障转移”或“无故障转移”
  • 合并标记为“故障转移”的重叠或并排的间隔
图4:支持向量机模型确定与数据中心故障转移对应的时间间隔。

一旦从数据集中删除故障转移间隔,我们就会留下缺失的值,为了使时间序列连续,必须对这些值进行计算。朴素的imputation方法,如线性插值,易于使用,但产生不现实的值。必须考虑通过时间序列分解算法获得的趋势和季节成分,以便估算值看起来真实。在Uber,我们利用了一种混合imputation方法,它结合了线性插值和黄土的季节和趋势分解图(STL)来输入缺失的值。

图5:当我们比较线性和基于季节性的插值技术对数据进行预处理时,季节性更真实地代表了缺失的时间序列数据。

数据预测和回测

对于时间序列预测,我们利用内部预测API,该API使用集成方法包含华宇电脑Holt-Winters,θ模型。每个模型的预测都被考虑到同等的权重,尽管对于未来的预测用例,性能更好的模型可能比其他模型的权重更高。此外,预测API实现了自动预测,可对模型进行微调hyperparameters无需手动输入。

为了评估集成方法的性能,我们必须生成一个度量来量化预期和实际预测之间的误差。与传统的机器学习测试方法不同,时间序列数据是按顺序排列的,因此不能随意打乱点。时间序列数据需要持续测试,或回测,它使用交叉验证来评估模型在滚动窗口上的性能。

val过程量化了预期和实际预测之间的误差,为我们提供了许多误差指标:平均误差(ME),平均绝对误差(美),平均绝对百分比误差(MAPE)和加权平均绝对百分比误差(wMAPE)。我们大多使用wMAPE来确定集成方法的误差,因为它是一个无偏的、信息丰富的和一致的度量。

wMAPE分数越低,我们对模型的预测就越有信心,但由于时间序列数据可能非常不稳定,误差通常是有限度的。使用我们系统的服务所有者发现,wMAPE评分的预报信息量在10- 15%之间,这是我们试图为平台上的每个服务实现的目标。

图6:我们认为对于单个服务RPS的这个示例预测的误差范围(达到12% wMAPE)是可以接受的。

容量安全验证

每周的预测和回测分数可以通过HTTP API访问。对执行本地容量安全测试感兴趣的服务所有者可以获取度量的当前状态,计算当前状态与预测状态之间的增量,并使用生成增量负载下得很大的冰雹这是Uber的负载测试框架。这提供了对服务是否正确提供的洞察:如果负载测试失败,则表明该服务将来可能会出现性能下降。

图7:使用我们的预测系统,开发人员可以模拟一周后几天的每小时负载。

我们的预测系统的目标是简化预测重要指标的过程,进行本地容量安全演练,并接收关于服务是否正确提供的反馈。通过该服务的发展,我们发现在足够的运行数据条件下,精确的时间序列预测是可行的。我们需要两套广泛的统计技术,一套用于预处理,另一套用于预测。基于集成的模型在灌输各种模型的观点方面也很强大。

前进

通过操作度量预测和api驱动的负载生成,可以对单个微服务进行自适应、自动化的容量安全测试。SLA遵守可以主动验证,而不是追溯验证。

未来,我们打算将这一过程完全自动化,因此可靠性工程师无需动动按钮就可以确保起下钻流程服务的容量安全。这还将允许在不那么关键的系统上进行快速试验和迭代,从而为开发人员带来更大的灵活性和更好的服务。

对构建下一代可靠性平台感兴趣吗?考虑加入我们的团队

评论