Envoy 的监听器连接平衡
Envoy 的监听器连接平衡
代理*是后端的前端。无论是 API 网关、第 7 层负载均衡器还是 CDN,代理服务器都会从客户端接收大部分连接。这使得尽可能快地接受大量连接并以平衡的方式处理这些连接上的逻辑请求变得具有挑战性。
我讨论了 通用架构 用于管理与多线程代理和后端应用程序的连接的模式。然而,当我发布那篇文章时,我被提醒说 Envoy 在管理连接方面有一种有趣的架构风格。让我们回顾一下 Envoy 默认如何管理连接以及监听器连接平衡是如何工作的。我们在本文的所有讨论中都假设使用 TCP。
套接字分片——SO_REUSEPORT
就像 HAProxy 和 NGINX 一样,套接字分片是 Envoy 中的默认侦听器配置。这意味着 Envoy 的所有侦听器线程都将侦听用户配置的同一端口。通常这会导致侦听器错误,因为没有两个进程(线程)可以在同一端口上侦听。但是,如果您指定套接字选项 ( SO_REUSEPORT ) 在侦听器上,将允许每个线程在创建自己的套接字的同一端口上侦听。
这有效地 创建 每个绑定到相同端口/地址的套接字的队列。当操作系统在 TCP 三向握手中执行最终的 ACK 时,它将把准备好的连接移动到一个 接受 queue 拥有套接字的线程可以调用 accept() 来为连接创建文件描述符并开始读取和写入连接。操作系统决定将连接移动到哪个队列的方式是基于四个元组的哈希(源 ip/源端口/目标 ip/目标端口)。我们知道目的ip和端口是一样的,这里变化的是源端。对于大量连接,这些连接将分布在所有套接字上,如果每个线程都拥有一个套接字,则每个线程将被分配一定数量的连接。
套接字分片的问题
所有套接字和线程之间的连接实际上是否平衡良好?并非如此,散列算法远非完美,一个线程比其他线程获得更多连接的可能性非常高。当您有大量的短期连接(例如来自浏览器的 HTTP/1.1 连接)时,这并不重要。但是,如果您的客户使用长期连接,每个连接都有大量请求,则可能会成为问题。这在 gRPC、h2 或从服务网格发起的连接(代理与代理通信)中尤其如此,一旦您建立 TCP 连接,客户端将通过该连接发送各种请求。因此,无论哪个糟糕的线程最终托管 gRPC 连接,都将忙于执行来自客户端的大量多路复用请求。
这里任何数量的不平衡都会显着影响性能。如果您有 50 个 gRPC 连接和 4 个线程,则套接字分片 (SO_REUSEPORT) 哈希算法可能会将 35 个连接分配给线程 1、5 个连接分配给线程 2、9 个连接线程 3 和线程 1 上的 1 个连接。线程 1 成为热点,而其他线程没有那么忙。
Envoy 是如何解决这个问题的?
Envoy 意识到了这个问题,恰好落在繁忙的线程 1 上的客户端将遭受性能下降,更不用说线程 1 中的上游后端连接池将耗尽。因此,Envoy 发明了侦听器连接平衡,其中线程将开始相互通信(它们以前不这样做)并交换套接字以平衡负载,如果一个线程有更多的套接字。我没有足够的技术细节来说明这是如何完成的,因为 文档 没有提及太多细节。
Envoy Listener connection balancing
在我看来,虽然我觉得这种架构很有趣,但我不得不说它没有那么有效,这就是原因。即使你有 4 个线程并且每个线程都分配了相同数量的 gRPC 连接,你仍然缺乏关于 加载 .线程 1 可能由一个贪婪的客户端提供服务,发送大量需要高处理的逻辑请求,而线程 2-4 托管要求不高的客户端。这是基于消息的负载平衡可能有用的地方,侦听器线程不进行处理,而是解析应用程序请求,然后将请求转发到执行工作的工作线程。侦听器线程知道每个工作线程正在做多少工作,并且可以产生真正的负载平衡环境。
学习网络工程的基础知识以构建有效的后端应用程序,开始我的 udemy 课程 https://network.husseinnasser.com 获取优惠券和支持。
*这里的代理是指代理和反向代理。
- 这里的代理请求处理是指解析TCP连接流寻找L7应用请求。它还包括将请求写入后端上游连接。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明