Apache 在处理反向代理和负载均衡时,mod_proxy_balancer 模块承担了请求分发与健康检查的核心职责。要让不同性能的后端服务器获得与其能力匹配的流量,不能只做简单轮询,而需要为每个节点设置一个权重值,再交给负载均衡算法解释。Apache 将权重参数命名为 loadfactor,它定义在 BalancerMember 指令中,默认值是 1,取值范围通常为 1 到 100。这个值并不是百分比,而是一个相对系数,例如 5 比 1 表示五倍的分配比例。本文将从权重参数基础、三种内置算法、实际配置验证和调优误区四个角度,说明 Apache 后端服务器权重分配算法的使用方法。

一、Apache 负载均衡模块与权重参数基础
在 Apache 的反向代理体系中,负载均衡功能由 mod_proxy 配合 mod_proxy_balancer 共同完成。后端服务器集群通过 <Proxy balancer://集群名> 块定义,集群中的每一台服务器使用 BalancerMember 指令声明。loadfactor 就是 BalancerMember 的一个关键参数,它告诉调度器当前节点相对于其他节点的处理能力水平。例如三个后端节点分别设置 loadfactor 为 5、1、2,那么在 byrequests 策略下,三台机器接收到的请求比例大致为 5:1:2。
需要特别注意的是,loadfactor 只表示相对权重,不要求所有节点权重之和等于 100。比如权重 5、1、2 与权重 50、10、20 在比例关系上是等价的。实际配置时建议使用较小的整数,便于观察和调整。如果某个节点完全不想承接业务流量,除了将 loadfactor 设为最小值外,更推荐直接将该成员从集群中移除,或使用 status=+H 将其标记为热备节点,这样语义更清晰。
下面是一个最基础的权重集群定义:
<Proxy balancer://backendpool>
BalancerMember http://192.168.1.10:8080 loadfactor=5
BalancerMember http://192.168.1.11:8080 loadfactor=1
BalancerMember http://192.168.1.12:8080 loadfactor=2
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass / balancer://backendpool/
ProxyPassReverse / balancer://backendpool/
这段配置定义了一个名为 backendpool 的集群,其中三台后端服务器权重分别是 5、1、2。代理规则将所有请求转发到该集群,并由 lbmethod=byrequests 指定使用基于请求计数的权重分配算法。如果不显式设置 lbmethod,Apache 默认也会使用 byrequests,但显式写明有助于配置可读性。
二、三种算法中的权重分配机制
Apache mod_proxy_balancer 提供了多种内置负载均衡算法,其中与权重密切相关的有三种:byrequests、bytraffic 和 bybusyness。它们虽然都读取 loadfactor 参数,但对权重的解释方式完全不同。
1. byrequests 请求计数加权
byrequests 是 Apache 默认的调度算法,也是最容易理解的一种。它根据每个后端节点的 loadfactor 值构造一个加权请求表,权重越大的节点在调度循环中出现次数越多。假设集群中有三台节点,权重分别为 5、1、2,那么理想情况下,每 8 个请求中大约有 5 个分配给第一台、1 个分配给第二台、2 个分配给第三台。这种算法适合请求处理耗时接近、业务逻辑相对轻量的场景。
需要注意的是,byrequests 并不保证严格按权重进行短时间内的精准轮询。它关注的是长期统计意义上的比例,而不是每 8 个请求必然出现精确的 5:1:2 序列。如果后端节点之间存在较大的响应时间差异,即使请求数量按权重分配,实际并发压力也可能不均衡,这时就需要考虑其他算法。
2. bytraffic 流量加权
bytraffic 算法的权重与传输字节数相关。Apache 会记录每个后端节点已经处理的流量大小,再用该值除以 loadfactor,选择相对流量压力最小的节点承接新请求。权重的核心含义是:在已经传输相同字节数的情况下,权重越大的节点被判定为越不繁忙,因此能继续获得更多新请求。这种设计适合大文件下载、静态资源服务或接口响应体大小差异明显的业务。
举例来说,如果节点 A 的 loadfactor 为 5,节点 B 为 1,即使节点 A 已经传输了 500MB 数据,节点 B 只传输了 100MB,由于 500/5 等于 100,它与节点 B 的相对流量压力仍然是相同的。这样就能避免高带宽节点因为单次传输大文件而迅速被判定为过载。
3. bybusyness 繁忙度加权
bybusyness 则更关注实时并发情况。它会统计每个后端节点当前正在处理的请求数量,然后将这个数字除以 loadfactor,选择结果最小的节点接纳新请求。也就是说,权重在这里充当了容忍并发压力的系数。同样是并发 10 个请求,loadfactor 为 5 的节点计算值只有 2,而 loadfactor 为 2 的节点计算值为 5,前者会被认为更空闲。
这种算法适合请求耗时波动较大的应用,比如动态接口、数据库查询频繁的业务。它能够在高权重节点已经积累较多并发时,及时将请求引流到相对空闲的低权重节点,避免高权重节点被压垮。缺点是动态计算会带来一定调度开销,而且对短连接的判断效果不如长连接明显。
为了更直观地对比三种算法,可以整理如下:
| 算法 | 权重作用 | 适用场景 |
|---|---|---|
| byrequests | 请求数量按 loadfactor 比例分配 | 请求耗时相近、业务逻辑轻 |
| bytraffic | 传输字节数除以 loadfactor 后比较 | 响应体大小差异大、带宽敏感 |
| bybusyness | 并发请求数除以 loadfactor 后比较 | 耗时波动大、长连接业务 |
三、Apache 后端权重配置示例与验证方法
实际生产环境中,权重配置通常放在完整的虚拟主机配置中。下面是一个包含权重集群、反向代理映射和状态管理页面的完整示例:
<VirtualHost *:80>
ServerName ipipp.com
<Proxy balancer://backendpool>
BalancerMember http://192.168.1.10:8080 loadfactor=5 timeout=5s
BalancerMember http://192.168.1.11:8080 loadfactor=1 timeout=5s
BalancerMember http://192.168.1.12:8080 loadfactor=2 timeout=5s
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass / balancer://backendpool/
ProxyPassReverse / balancer://backendpool/
<Location /balancer-manager>
SetHandler balancer-manager
</Location>
</VirtualHost>
完成配置后重启 Apache,访问 /balancer-manager 路径可以查看 balancer 的运行状态。页面中每个后端节点的 Load 字段显示的就是当前 loadfactor 值,Elected 字段表示该节点被选中处理请求的总次数,Busy 字段表示当前正在处理的请求数。通过连续发送测试请求,可以观察 Elected 字段的增长是否符合权重比例。
如果后端服务部署在独立的 Tomcat、Node.js 或 PHP-FPM 进程上,可以结合各节点自己的访问日志进行验证。下面是一个简单的批量请求测试命令:
for i in $(seq 1 40); do
curl -s -o /dev/null http://ipipp.com/
done
发送 40 个请求后,分别查看三台后端服务器的访问日志数量。对于权重 5:1:2 的集群,三个节点收到的请求数大致应接近 25、5、10。单次测试可能存在偏差,建议多次发送并观察长期分布。如果实际分布与预期差距较大,需要检查是否启用了会话保持、健康检查失败或后端响应异常。
四、权重调优实践与常见误区
很多运维人员习惯于只修改 loadfactor,却忽略了 lbmethod 的影响。如果集群之前被设置为 bybusyness,那么 loadfactor 不再直接表示请求数量比例,而是作为并发繁忙度的调节因子。此时单纯增大权重确实能让节点获得更多请求,但幅度并不像 byrequests 那样直观。因此在调整权重前,应当先确认当前生效的 lbmethod,并在配置文件中显式声明。
另一个常见误区是把 loadfactor 当作百分比。比如以为设置 80、10、10 就是分别承担 80%、10%、10% 的流量。实际上 Apache 只会按照相对比例进行调度,并不强制总和必须为 100。如果只有两个节点,权重分别为 3 和 1,那么第一个节点大约承担四分之三的请求,而不是 3% 的请求。理解这一点可以避免配置时出现不必要的困惑。
权重调优不应该一次到位,而是要在监控基础上逐步调整。建议先观察各后端节点的 CPU、内存、响应时间和错误日志,找出真正的性能瓶颈。如果 CPU 和内存占用差异较大,可以优先调整 byrequests 的 loadfactor;如果带宽消耗明显不均衡,应考虑切换 bytraffic;如果请求耗时波动大且节点繁忙程度差异明显,则适合使用 bybusyness。调整后通过 balancer-manager 页面和压测工具验证,才能让权重分配算法真正发挥均衡作用。