У нас проблема с относительно глупым балансировщиком нагрузки, который находится перед веб-сервером 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 (Bad Gateway) код состояния.
Примеры правил 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;
}