HAProxy 是如何实现其速度的?

问题描述 投票:0回答:1

HAProxy 在进行负载均衡时如何避免请求时间开销?

我测试了 HAProxy,并将其与用 Twisted (Python) 编写的简单端口转发器进行比较。在我的初步测试中,与直接向后端服务器发出 HTTP 请求相比,通过 HAProxy 负载均衡器发出 HTTP 请求不会增加请求时间的开销 [1]。而我自己的 python 脚本在响应时间上增加了约 3 倍的开销。

现在我的脚本是用 Python 编写的,HAProxy 用 C 语言编写的,因此,HAProxy 的优点是可以避免 Python 代码所经历的调用开销(从 Python 代码到系统调用)。但这是否可以解释性能上的巨大差异,或者 HAProxy 是否利用了一些操作系统技巧来进一步提高性能?我尝试分析我的 Python 代码,但它没有揭示 Python 代码中的任何热点,因此我猜测它大部分时间都花在分析中未考虑到的系统调用中。

[1]:据 ab 报告,有 100 个并发连接和 10,000 个总请求。 HAProxy 的平均时间是 37 毫秒,而我的 Python 脚本是 128 毫秒。

设置

该设置是一个 TCP 负载均衡器,具有两个后端 Nodejs 服务器,仅提供静态文本。我故意想测试TCP负载平衡,然后测试协议变成了HTTP。这三台机器都是来自 Digital Ocean 的虚拟主机,单线程,512MB RAM,1 核。 Python 脚本可以在这里看到,我的 haproxy.cfg 可以在这里找到

python twisted haproxy
1个回答
11
投票

原来

HAProxy
网站已经涵盖了这个领域(我的错误忽略了它)。答案基本上是大量的低级优化。直接从HAProxy网站复制过来:

HAProxy 涉及操作系统架构中常见的几种技术,以实现绝对最大性能:

  • 单进程、事件驱动的模型大大降低了上下文切换的成本和内存使用量。一毫秒内处理数百个任务是可能的,每个会话的内存使用量约为几千字节,而类似

    Apache
    的模型消耗的内存更多为每个进程的兆字节量级。

  • O(1)
    系统上的事件检查器(
    Linux
    FreeBSD
    )允许即时检测数万个连接上的任何事件。

  • 尽可能在读取和写入之间进行单缓冲,无需任何数据复制。这节省了大量的

    CPU
    周期和有用的内存带宽。通常,瓶颈是
    I/O
    和网络接口之间的
    CPU
    总线。在 10
    Gbps
    时,内存带宽也可能成为瓶颈。

  • 使用

    splice()
    下的
    Linux
    系统调用可以实现零拷贝转发,并从
    Linux
    3.5 开始实现真正的零拷贝。这允许小型 3 瓦以下设备(例如
    Seagate Dockstar
    )以 1
    HTTP
    转发
    gigabit/s
    流量。

  • MRU
    内存分配器使用固定大小的内存池进行即时内存分配,有利于热缓存区域而不是冷缓存区域。这极大地减少了创建新会话所需的时间。

  • 工作分解,例如一次多个

    accept()
    ,以及在多进程模式下运行时限制每次迭代
    accept()
    的数量,以便负载在进程之间均匀分配。

  • 基于树的存储,大量使用我多年来开发的

    Elastic Binary
    树。这用于保持计时器有序、保持运行队列有序、管理循环和最少连接队列,而只需
    O(log(N))
    成本。

  • 优化的

    HTTP
    标头分析:标头被动态解析和解释,并且解析被优化以避免重新读取任何先前读取的内存区域。当到达缓冲区末尾且标头不完整时,将使用检查点,这样当读取更多数据时,解析就不会从头开始重新开始。在
    HTTP
    上解析平均
    Pentium-M 1.7 GHz
    请求通常需要 2 微秒。

  • 小心减少昂贵的系统调用次数。默认情况下,大部分工作都是在用户空间完成的,例如时间读取、缓冲区聚合、文件描述符启用/禁用。

© www.soinside.com 2019 - 2024. All rights reserved.