如果我们在使用网络系统,那么可能会非常关心延迟问题。在面对一组服务器时,我们需要思考选择哪种负载均衡算法。如果可以直观了解不同负载均衡器配置的具体情况,那对我们做决策将非常有帮助。这样还能最小化环境中的延迟,以避免意外情况发生。

众所周知,负载均衡器主要负责将网络请求分发到服务器集群上(这在 Envoy 中称为上游)。我们一般追求最大化网络请求的服务效率。这意味着服务器的 CPU 利用率更高,并且发送方的等待时间更短(延迟)。通常在有延迟的地方,我们还会发现在某个部位正形成一个队列。因此,我在研究负载均衡器方案,以最小化上游的队列。

本文将简要介绍 Envoy 中的各种负载均衡算法,并通过一些模拟案例来展示它们的表现。这里不讨论重试策略、断路、紧急路由,负载均衡器优先级,以及它们对负载均衡的影响。

模拟流量

接下来的每个模拟案例都会通过 Envoy 进程将具有固定 RPS 的 HTTP 请求发送到由 10 个 HTTP 服务器组成的集群上。服务器接受一个请求后,会休眠一段时间(我们称其为“服务时间”),再以 200 状态进行响应。

模拟的一般拓扑结构

如果特定服务器同时处理多个请求,它将反复随机选择一个,并休眠 100us,直到满足该请求的“服务时间”,这近似体现了并发请求对延迟的影响。当每个服务器都形成队列并为多个请求提供服务时,每个请求的响应时间将增加。需要注意的是,如果我们没有让每个请求都具有相同的休眠时间,并且没有实际的延迟分布,那么服务器上的排队将对尾部延迟造成相当的影响。

延迟和 RPS 编号的细节这里就不讨论了,因为我们关心的是队列的形成原因,以及队列与负载均衡算法之间的关系。由于我们在控制 RPS 和请求延迟,因此只有两者之间的关系才对排队行为有影响。

现在,让我们来看个好东西 —— 负载均衡器!

随机负载均衡

Envoy 支持的最简单的负载均衡器是随机负载均衡器,它的节点、端点是通过随机选择决定的。随机法是将请求分发到一组上游节点的最简单方法,也是最容易实现的方法。100 万个选择在通过同一个随机选择算法处理后,将会均匀地分布在 10 个节点池中:

使用随机选择的节点分布直方图

请求均匀地分配了!这样就好了么?

并非如此简单。让我们看一下通过随机负载均衡的 10 个节点请求分配情况。

下图是我们的模拟结果,其中每条线代表一个不同的端点,Y 轴是在模拟过程中,特定时间点该端点未完成的请求数: