HAProxy
在进行负载平衡时,如何避免请求时间开销?
我测试HAProxy
并将其与用Twisted
(Python
)编写的简单端口转发器进行比较.在我的初步测试中,与直接连接到后端服务器相比,HTTP request
通过HAProxy
负载均衡器增加overhead[1]
请求时间HTTP request
.而我自己的python脚本会增加~3x overhead
响应时间.
现在,我的剧本是写在Python
和HAProxy
中C
,因此是先验的,HAProxy
具有避免调用开销(从准备的优点Python
代码syscalls
),该Python
代码的经验.但这可以解释性能上的巨大差异,还是HAProxy
利用一些操作系统技巧来进一步改善性能?我尝试分析我的Python
代码,但它没有透露Python
代码中的任何热点,所以我的猜测是它花费的大部分时间syscalls
都没有在分析中考虑.
[1]:由ab报告,有100个并发连接和10,000个总请求.平均时间为HAProxy
37毫秒,对于我的Python
脚本,它是128毫秒.
该设置是一个TCP
带有两个后端nodejs
服务器的负载均衡器,只提供静态文本.我故意想测试TCP负载平衡,然后测试协议就变成了HTTP
.这三台机器都是虚拟主机Digital Ocean
,单线程,512MB Ram,1核心.
可以在这里看到Python脚本,我的haproxy.cfg可以在这里找到
事实证明,该HAProxy
网站已经涵盖了这个领域(我忽略了它的错误).答案基本上是很多低级优化.直接从HAProxy网站复制:
HAProxy涉及操作系统体系结构中常见的几种技术,以实现绝对最大性能:
单进程,事件驱动模型大大降低了上下文切换和内存使用的成本.可以在一毫秒内处理数百个任务,并且每个会话的内存使用Apache
量大约为几千字节,而类似模型中消耗的内存更多地是每个进程的兆字节数量级.
O(1)
系统上的事件检查器,允许它(Linux
和FreeBSD
)允许在成千上万的任何连接上即时检测任何事件.
单缓冲,尽可能在读取和写入之间不进行任何数据复制.这节省了大量CPU
周期和有用的内存带宽.通常,瓶颈将是网络接口I/O
之间的总线CPU
.在10 Gbps
,内存带宽也可能成为瓶颈.
使用splice()
系统调用可以实现零拷贝转发Linux
,并从Linux
3.5 开始实现真正的零拷贝.这允许诸如a的小于3瓦的设备在一个Seagate Dockstar
处转发HTTP
流量gigabit/s
.
MRU
内存分配器使用固定大小的内存池进行直接内存分配,有利于热缓存区域而不是冷缓存区域.这大大减少了创建新会话所需的时间.
工作因子,例如accept()
一次多次,以及accept()
在多进程模式下运行时限制每次迭代次数的能力,以便在进程之间均匀分配负载.
以树为基础的存储,大量使用Elastic Binary
我已经开发了几年的树.这用于保持定时器的顺序,以保持命令的运行队列,管理循环和最少conn队列,只需要一个O(log(N))
成本.
优化的HTTP
头部分析:头部被解析,即时解释,并且优化解析以避免重新读取任何先前读取的内存区域.当使用不完整的头到达缓冲区的末尾时使用检查点,这样当读取更多数据时,解析不会从头开始.解析平均HTTP
请求通常需要2微秒Pentium-M 1.7 GHz
.
小心减少昂贵的系统调用次数.大多数工作默认在用户空间中完成,例如时间读取,缓冲区聚合,文件描述符启用/禁用.