mod-proxy-core 针对不同需求提供 3 种不同的负载均衡器:轮询 (Round Robin)、最短队列优先 (Shortest Queue First) 和 CARP。
我们可以将这些均衡器分为两类
- 按分布负载均衡 (RR, SQF)
- 按分离负载均衡 (CARP)
轮询 (Round Robin)
轮询 (Round Robin) (RR) 简单明了。
如果您有 3 台主机
- A1
- A2
- A3
第一个请求发送到 A1,第二个发送到 A2,第三个发送到 A3。第四个请求又从 A1 开始。
我们采用了一种略有不同的实现方式。我们不是真正地从 A1 到 A2 到 A3,而是选择所有活跃的后端并随机挑选一个。平均而言,每个主机获得的请求数量相同。
最短队列优先 (Shortest Queue First)
轮询 (RR) 有一个小问题。如果 A1 比 A2 和 A3 慢,那么快速的后端将获得与 A1 相同数量的请求。
SQF 试图将这一点考虑在内,并以队列长度作为均衡的基础。
第一个请求发送到 A1,需要 10 秒才能完成。与此同时,我们收到另外 4 个请求,A2 和 A3 在 2 秒内执行完毕。
两秒钟后,情况如下
- A1 还需要 8 秒 [q-len: 1]
- A2 空闲 [q-len: 0]
- A3 空闲 [q-len: 0]
请求 3 发送到 A2
- A1 还需要 8 秒 [q-len: 1]
- A2 需要 2 秒 [q-len: 1]
- A3 空闲 [q-len: 0]
请求 4 发送到 A3
- A1 还需要 8 秒 [q-len: 1]
- A2 需要 2 秒 [q-len: 1]
- A3 需要 2 秒 [q-len: 1]
如果现在有另一个请求进来,我们会将其放入积压队列。
基准测试
这必须进行基准测试。幸运的是,我家里有足够的硬件,所以我们有 4 台机器可以参与测试
- 客户端 (.23): 一台 Mac Mini, 1.2GHz, 100Mbit
- 代理 (.27): AMD64 3000+, Linux 2.6.x, 1Gbit
- 后端-1 (.22): Intel P4 1.2GHz, WinXP 32-bit
- 后端-2 (.25): AMD64 X2, 3500+, Win2003 64-bit
后端运行的是从 MSI 安装的 Apache 2.2.x,并启用了 mod_status。
代理是安装了 mod-proxy-core 的 lighty 1.5.0-r1435
$SERVER["socket"] == ":1445" { proxy-core.protocol = "http" # proxy-core.balancer = "round-robin" proxy-core.balancer = "sqf" proxy-core.backends = ( "192.168.178.25:80", "192.168.178.22:8080" ) # proxy-core.backends = ( "192.168.178.22:8080" ) # proxy-core.backends = ( "192.168.178.25:80" ) proxy-core.max-pool-size = 32 }
后端默认提供 htdocs/ 文件夹中 44 字节的 index.html 文件。
客户端始终运行相同的命令
$ ab -k -n 100000 -c 16 http://192.168.178.27:1445/
作为第一次测试,我们只启用 .25,即那台双核机器
Requests per second: 2833.60 [#/sec] (mean)
仅 .22 [我用了 3 年的迅驰笔记本] 得到的结果是
Requests per second: 1249.45 [#/sec] (mean)
使用 RR 会在两台主机上均匀分配请求。我们预计最大请求速率不会超过最慢后端请求速率的两倍。
均衡器 | 每秒请求数 | .22 请求数 | .25 请求数 | .27 空闲率 |
RR | 2122 | 50122 | 49896 | 50% |
SQF | 3213 | 30970 | 69048 | 25% |
您可以看到 SQF 如何根据后端的能力进行调整并很好地进行均衡,而 RR 只是按部就班地执行,最终导致吞吐量大大降低。
顺便说一句:如果禁用 keep-alive,SQF 的每秒请求数从 3213 下降到 2678,RR 则从 2122 下降到 1835。
代理服务器(我们的 lighty)对 CPU 的利用率很高,我已找到优化代理代码以减少 CPU 使用的方法。这不会对本次基准测试的性能产生太大影响,因为后端已经达到 100% 负载。