У нас проблема с относительно глупым балансировщиком нагрузки, который находится перед веб-сервером Apache. Веб-сервер Apache снова является обратным прокси-сервером для сервера приложений.
Проблема начинается, когда приложение выходит из строя. Это заставляет Apache выдавать код ошибки.
Проблема в том, что loadblancer учитывает только жесткую ошибку tcp для удаления сервера из пула. Это означает, что страницы с ошибками будут проходить через балансировщик нагрузки к пользователю, а не сервер, просто удаляемый из пула.
Можно ли настроить Apache для отклонения запроса tcp при бэкэнд-ошибке?
Haproxy может отклонять TCP-соединения на основе динамических условий, включая количество серверов, доступных на бэкэнде. Ключевое слово config - это соединение tcp-request. (Ссылка на документы ниже.)
Так что, может быть, поставить 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
Я был бы счастлив немного конкретизировать это, если вы думаете, что можете это использовать. Это интересная проблема.
Вероятно, это не будет работать с самим apache httpd. Проблема в том, что ваше неудачное приложение заставляет apache httpd генерировать ошибку. Эта ошибка возникает только тогда, когда вы действительно запрашиваете URL-адрес из этого приложения. Apache httpd нужен URL-адрес, чтобы решить, является ли это ошибкой, и чтобы получить URL-адрес от клиента, ему необходимо TCP-соединение.
Что вы можете сделать в качестве обходного пути: вы можете написать довольно простой скрипт, который считывает поток ErrorLog на stdin, а затем блокирует запросы от ваших балансировщиков нагрузки (возможно, iptables), когда ошибки начинают происходить. Затем этот сценарий можно настроить как приемник журнала ошибок apache httpd с помощью директивы ErrorLog.
Это отключило бы внутренний сервер apache httpd, но никогда не включит его автоматически.
Я перенесу логику в балансировщик нагрузки, если нет возможности заменить существующий балансировщик нагрузки, установите небольшой nginx на каждом сервере Apache для прокси-соединения.
[Пользователь] - [Балансировщик нагрузки] - [Nginx] - [Apache]
Используя nginx как балансировщик нагрузки или обратный прокси у вас есть доступ к ответам восходящего потока (в вашем случае Apache), и вы можете создавать правила, которые оценивают код ответа, прежде чем отвечать конечному клиенту:
$ upstream_status сохраняет код состояния ответа, полученного от вышестоящего сервера. Коды состояния нескольких ответов разделяются запятыми и двоеточиями, как адреса в переменной $ upstream_addr. Если сервер не может быть выбран, переменная сохраняет код состояния 502 (Плохой шлюз).
Примеры правил Nginx
Вызовите API балансировщика нагрузки, чтобы удалить узел, если он доступен:
if ($upstream_status != 200) {
return 301 return 301 http://loadbalance/api/remove/node;
}
Вызов локального скрипта (пожалуйста, проверьте безопасность), чтобы убить Apache и попросить пользователя перезагрузить страницу (в следующий раз он будет использовать другой сервер). Оно использует ngx_http_lua_module.
if ($upstream_status != 200) {
content_by_lua_block {
os.execute("/bin/killapache.sh")
}
return 301 https://$host$request_uri;
}