我们遇到了一个问题,那就是位于 Apache Web 服务器前面的负载均衡器相对比较笨重。Apache Web 服务器又是应用服务器的反向代理。
当应用程序崩溃时,问题就开始了。这会导致 Apache 抛出错误代码。
问题在于,负载平衡器仅考虑从池中移除服务器的硬 TCP 错误。这意味着错误页面将通过负载平衡器发送给用户,而不是服务器直接从池中移除。
是否可以配置 Apache 以拒绝后端的 tcp 请求并出现后端错误?
答案1
Haproxy 可以根据动态条件(包括后端可用的服务器数量)拒绝 tcp 连接。配置关键字是 tcp-request connection。(下面的文档链接。)
因此,也许将 haproxy 放在 Apache 前面(我知道,我知道!三层?!?!)或者也许使用 haproxy 代替 Apache。
可能看起来像这样(未经测试):
frontend http-in
bind *:80
mode http
tcp-request connection reject if nbsrv(appfarm) lt 1
default_backend appfarm
backend appfarm
server appsrv01 127.0.0.1:8888 check
如果你觉得有用的话,我很乐意进一步阐述一下。这是一个有趣的问题。
答案2
这可能无法与 apache httpd 本身配合使用。问题是您的应用程序失败导致 apache httpd 生成错误。只有当您实际从该应用程序请求 URL 时才会发生此错误。Apache httpd 需要 URL 来决定这是否是错误,并且要从客户端获取 URL,它需要 TCP 连接。
解决方法:您可以编写一个相当简单的脚本,读取 stdin 上的 ErrorLog 流,然后在错误开始发生时阻止来自负载均衡器(可能是 iptables)的请求。然后可以使用 ErrorLog 指令将该脚本配置为 apache httpd 错误日志的接收器。
这将禁用 apache httpd 后端服务器,但永远不会自动重新启用它。
答案3
我会将逻辑转移到负载均衡器,如果无法替换现有的负载均衡器,则在每个 Apache 服务器中安装一个小型 nginx 来代理连接。
[用户] - [负载均衡器] - [Nginx]—[阿帕奇]
通过使用nginx 作为负载均衡器或反向代理您可以访问上游响应(在您的情况下是 Apache),并且可以制定在回复最终客户端之前评估响应代码的规则:
$上游状态保存从上游服务器获得的响应的状态码。多个响应的状态码像 $upstream_addr 变量中的地址一样用逗号和冒号分隔。如果无法选择服务器,则变量保存 502(Bad Gateway)状态码。
Nginx 示例规则
如果可用,调用负载均衡器 API 来删除节点:
if ($upstream_status != 200) {
return 301 return 301 http://loadbalance/api/remove/node;
}
调用本地脚本(请检查安全性)来终止 Apache 并告诉用户重新加载页面(下次将使用另一个后端)。它使用ngx_http_lua_模块。
if ($upstream_status != 200) {
content_by_lua_block {
os.execute("/bin/killapache.sh")
}
return 301 https://$host$request_uri;
}