Apache 代理负载均衡后端服务器故障检测

Posted

技术标签:

【中文标题】Apache 代理负载均衡后端服务器故障检测【英文标题】:Apache proxy load balancing backend server failure detection 【发布时间】:2012-08-05 19:50:47 【问题描述】:

这是我的场景(由我的前任设计):

两台 Apache 服务器为多个混合后端 Web 服务器(Apache、IIS、Tomcat 等)提供反向代理服务。有些网站我们有多个后端网络服务器,在这些情况下,我们会执行以下操作:

<Proxy balancer://www.example.com>
    BalancerMember http://192.168.1.40:80
    BalancerMember http://192.168.1.41:80
</Proxy>
<VirtualHost *:80>
    ServerName www.example.com:80
    CustomLog /var/log/apache2/www.example.com.log combined
    <Location />
        Order allow,deny
        Allow from all
        ProxyPass balancer://www.example.com/
        ProxyPassReverse balancer://www.example.com/
    </Location>
</VirtualHost>

因此,在此示例中,我在代理服务器的配置中有一个站点 (www.example.com),该站点代理到两个后端服务器中的一个或另一个,192.168.1.40 和 .41 .

我正在对此进行评估,以确保我们的所有 Web 服务都具有容错能力(为此,我已经将两个反向代理服务器放入一个共享 IP 集群),并且我想确保负载平衡的后端服务器也是容错的。但是我无法确定后端故障检测(以及避免后端服务器故障的逻辑)是否内置在 mod_proxy_balancer 模块中......

因此,如果 192.168.202.40 出现故障,Apache 会检测到这一点(我会理解它是否首先接受失败的请求)并自动将所有请求路由到另一个后端 192.168.202.41?还是会继续平衡故障后端和运行后端之间的请求?

我在 mod_proxy 和 mod_proxy_balancer 的 Apache 文档中发现了一些线索,这些线索似乎表明可以检测到故障(“maxattempts = 放弃前的最大故障转移尝试次数。”、“failonstatus = 单个或逗号分隔的 HTTP 状态代码列表。如果设置,当后端返回列表中的任何状态代码时,将强制工作人员进入错误状态。”),但经过几天的搜索,我没有找到任何结论性的说法确保它(或至少“应该”)检测到后端故障和恢复。

我会说大多数搜索结果引用使用 AJP 协议将流量传递到后端服务器,这显然确实支持故障检测——但我的后端是 Apache、IIS、Tomcat 等的混合体,而且我相当肯定他们中的许多人不支持 AJP。它们也是 Windows 2k3/2k8 和 Linux(主要是 Ubuntu Lucid)机器的混合体,运行具有各种不同要求的各种不同应用程序,因此像 Backhand 和 LVS 这样的附加模块不适合我。

我还尝试通过创建一个这样的新测试站点来经验性地测试此功能:

<Proxy balancer://test.example.com>
    BalancerMember http://192.168.1.40:80
    BalancerMember http://192.168.1.200:80
</Proxy>
<VirtualHost *:80>
    ServerName test.example.com:80
    CustomLog /var/log/apache2/test.example.com.log combined
    LogLevel debug
    <Location />
        Order allow,deny
        Allow from all
        ProxyPass balancer://test.example.com/
        ProxyPassReverse balancer://test.example.com/
    </Location>
</VirtualHost>

其中 192.168.1.200 是一个未运行任何 Web 服务器的虚假地址,用于模拟后端故障。为一堆不同的客户端机器提供了测试站点没有问题,但是即使将 LogLevel 设置为调试,我也没有看到任何记录表明它检测到一个后端服务器已关闭......并且我想 100% 确保我可以在不影响生产站点的情况下关闭负载平衡的后端进行维护(当然,一次一个)。

【问题讨论】:

【参考方案1】:

http://httpd.apache.org/docs/2.4/mod/mod_proxy.html Section "BalancerMember parameters", property=retry:

如果到后端服务器的连接池工作者出现错误 状态,Apache httpd 不会将任何请求转发到该服务器,直到 超时到期。这使 [one] 可以关闭后端 服务器进行维护,稍后将其重新联机。值为 0 意味着总是在没有超时的情况下重试处于错误状态的工作人员。

但是,使用 mod_whatever 无法捕获其他故障情况,例如,运行已关闭应用程序的 IIS 后端。 IIS 已启动,因此可以建立连接并读取页面,只是该页面将始终为 500 内部服务器错误。在这里,您将不得不使用 failonerror 来捕获它并强制 worker 进入错误状态。

在所有情况下,一旦工作人员处于错误状态,流量将不会被定向到它。我一直在尝试不同的方式来处理第一次失败并重试它,但似乎总是有错误页面将其返回给客户端的情况。

【讨论】:

这里回复晚了,但这确实帮助了我。我不得不强制升级到 2.2.17,因为普通的 Lucid 存储库只有 2.2.14,它不支持“failonstatus”参数。暂时添加了 natty repos,更新到 2.2.17,现在一切似乎都正常了。谢谢! @David Newcomb 我发现唯一有效的解决方案(虽然它很丑)是使用maxattempts(见serverfault.com/questions/503531/…)。【参考方案2】:

“BalancerMember 参数”中有一个属性“ping”

阅读文档,听起来“ping”设置为 500 毫秒会在 mod_proxy 将您定向到 BalancerMember 之前发送请求。 mod_proxy 将等待来自 BalancerMember 的响应 500 毫秒,如果 mod_proxy 没有得到响应,它会但 BalancerMember 进入错误状态。

我厌倦了实现这一点,但它似乎对引导到现场 BalancerMember 没有帮助。

<Proxy balancer://APICluster>
    BalancerMember https://api01 route=qa-api1 ttl=5 ping=500ms
    BalancerMember https://api02 route=qa-api2 ttl=5 ping=500ms
    ProxySet lbmethod=bybusyness stickysession=ROUTEID
</Proxy>

http://httpd.apache.org/docs/2.4/mod/mod_proxy.html

Ping 属性告诉网络服务器在转发请求之前“测试”与后端的连接。对于 AJP,它会导致 mod_proxy_ajp 在 ajp13 连接上发送一个 CPING 请求(在 Tomcat 3.3.2+、4.1.28+ 和 5.0.13+ 上实现)。对于 HTTP,它会导致 mod_proxy_http 向后端发送 100-Continue(仅对 HTTP/1.1 有效 - 对于非 HTTP/1.1 后端,此属性无效)。在这两种情况下,参数都是等待回复的延迟时间(以秒为单位)。添加此功能是为了避免后端挂起和繁忙的问题。这将增加正常操作期间的网络流量,这可能是一个问题,但如果某些集群节点关闭或忙碌,它会降低流量。通过添加 ms 的后缀,延迟也可以设置为毫秒。

【讨论】:

以上是关于Apache 代理负载均衡后端服务器故障检测的主要内容,如果未能解决你的问题,请参考以下文章

负载均衡之----DR模式下LVS负载均衡 / keepalived后端故障检测 / Lvs+keepalived 实现高可用

Ubuntu16.04Apache负载均衡+集群

Haproxy相关概念解析

nginx做反向代理负载均衡 Java怎么获取后端服务器获取用户IP

nginx做反向代理负载均衡 Java怎么获取后端服务器获取用户IP

HAProxy的三种不同类型配置方案