Netflix中的自适应并发限制



Netflix痴迷于服务可用性。 我们已经在博客上不止一次地对其进行了审查,并告诉我们如何实现目标。 我们使用断路器,并发限制,混乱测试等。 今天,我们向您展示了另一种创新方法,该方法可以极大地提高应用程序在极端负载下的稳定性并避免级联的服务故障-并行连接的自适应限制。 无需再确定并行连接的限制,从而使系统保持较短的响应时间。 作为此公告的一部分,我们还将在公共领域发布一个简单的Java库,该库具有Servlet,控制程序和gRPC的集成功能。

让我们从基础开始


并行连接的限制是系统在特定时间点能够处理的最大请求数。 通常,此数量取决于有限的资源,例如中央处理器的处理能力。 通常,系统的并行连接限制是根据利特尔定律计算的,这听起来像这样:对于稳定的系统,并行连接的最大数量等于处理请求的平均时间与传入请求的平均强度的乘积(L =λW)。 系统无法立即处理超出并行连接限制的任何请求,因此它们将被排队或拒绝。 排队是一项重要功能,可让您在请求接收不均且需要不同时间处理的情况下充分使用系统。



如果队列没有限制,则可能会发生系统崩溃,例如,长时间以来,请求的强度高于其处理速度。 随着队列的增长,延迟也会增加,这会导致请求等待时间过多。 这一直持续到可用内存用完,然后系统崩溃。 如果您不跟踪增加的延迟时间,它将开始对呼叫服务产生负面影响,并导致级联系统故障。



并行连接限制的使用是一种标准做法,但是困难在于确定大型动态分布式系统的限制,在该系统中,诸如延迟时间和可能的并行连接数之类的参数不断变化。 我们解决方案的本质是动态确定并行连接限制的能力。 此限制可以表示为系统在性能开始下降(延迟时间增加)之前能够处理的传入请求(并行执行和排队)的数量。

解决方案


以前,Netflix员工通过耗时的性能测试和配置来确定手动并发连接限制。 结果数字在特定时间段内是正确的,但是由于部分故障,自动缩放或引入影响延迟时间的其他代码,很快系统的拓扑开始发生变化。 结果,该限制已过期。 我们知道我们有更多的能力,仅仅依靠静态确定连接限制已不再足够。 我们需要一种自动确定系统本身固有限制的方法。 同时,我们需要这种方法:

  1. 不需要体力劳动;
  2. 不需要中央协调;
  3. 可以在没有有关硬件或系统拓扑的任何信息的情况下确定限制;
  4. 适应系统拓扑的变化;
  5. 在实施和必要的计算方面很简单。

为了解决这个问题,我们转向了成熟的TCP拥塞跟踪算法。 该算法确定在不增加延迟时间或不超过等待时间的情况下可以并行传输的数据包的数量(即溢出窗口的大小)。 这些算法使用各种指示符来确定同时传输的数据包的限制,并相应地调整溢出窗口的大小。



图片中的蓝色表示与系统并行连接的未知限制。 首先,客户端发送少量并发请求,然后开始定期检查系统,以查看它是否可以通过增加溢出窗口来处理更多请求,直到造成延迟增加为止。 当延迟仍然增加时,发送方将确定其已达到限制,并再次减小溢出窗口的大小。 您可以在上面的图形中反映出这种对限制的连续测试。

我们的算法依赖于TCP拥塞跟踪算法,该算法考虑了最小延迟时间(不使用队列的最佳可能方案)与延迟时间之间的关系,该延迟时间在执行请求时定期进行测量。 该比率使得可以确定已经形成了引起延迟增加的队列。 该比率为我们提供了延迟时间变化的梯度或幅度: 梯度=(RTTnoload / RTTactual) 。 如果该值等于1,则说明没有队列,可以增加限制。 小于1的值表示队列已满,需要减少限制。 每次对延迟时间进行新的测量时,都会根据上述比率调整限制,并根据以下简单公式更改允许的队列大小:

_ = _ ×  + _ 

对于多次迭代,该算法计算出一个限制,该限制不仅允许将延迟时间保持在较低的水平,而且还可以在活动爆发时形成必要的请求队列。 可以配置有效的队列大小。 它用于确定并发限制可以增加多快。 作为默认大小,我们选择了当前极限值的平方根。 该选择归因于平方根的有用特性:较小的值与保证快速增长的限制相比将足够大,但是相反,较大的值则其相对值较小,这将增加系统的稳定性。

适应性限制


服务器端的自适应限制会拒绝过多的请求并保持较低的延迟,这使系统实例可以保护自己及其所依赖的服务。 以前,当不可能拒绝过多的请求时,每秒请求数量的任何稳定增加或延迟时间都会导致该时间的增加甚至最终导致整个系统的崩溃。 如今,在与其他稳定工具(例如自动扩展)一起使用时,服务可以摆脱不必要的工作负载并保持低延迟。



重要的是要记住,限制是在服务器级别设置的(并且没有任何协调),每个服务器的通信量可能急剧下降和增加。 因此,根据服务器的不同,检测到的限制和并发连接数可能会有所不同也就不足为奇了。 在多客户端云环境中尤其如此。 结果,一台服务器过载时可能会出现这种情况,尽管其余服务器将是空闲的。 同时,当平衡客户端的负载时,在几乎100%的情况下,只有一个重复请求将以可用资源到达服务器。 这还不是全部:没有更多的理由担心重复的请求会引发DDOS攻击,因为服务能够快速(不到一毫秒)拒绝流量,而对性能的影响最小。

结论


通过对并行连接使用自适应限制,无需手动确定服务在何种情况下应拒绝流量。 此外,它还提高了我们整个微服务生态系统的整体可靠性和可用性。

我们很高兴与您分享我们的实现方法和该解决方案的整体集成,您可以在github.com/Netflix/concurrency-limits的公共库中找到这些方法 。 我们希望我们的代码将帮助用户保护服务,使其免受级联故障和延迟增加的问题的困扰,并提高可用性。

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


All Articles