Как заставить HAProxy перезаписывать другой сервер, если в первом отсутствует файл? Мне нужно errorloc
но вместо перенаправления выполняется перезапись, поэтому клиент не знает о перенаправлении.
Мы разработали приложение с учетом NginX, которое одновременно использовало обратный прокси-сервер с балансировкой нагрузки и веб-сервер для статических файлов. Приложение основано на Опа framework, который требует закрепленных сеансов на основе файлов cookie - поддерживается как NginX, так и HAproxy. Проблема приложения - создание динамического контента. Он генерирует изображения по запросу, но после генерации они сохраняются на диске и могут быть доступны статически с детерминированным путем.
Проблема была легко решена с помощью NginX - он пытается прочитать локальный файл и использовать серверную часть с балансировкой нагрузки, только если файл отсутствует (еще не сгенерирован):
server {
server_name wkaliszu.pl;
location /thumb {
root /path_on_disk/to_cached_content;
expires 7d;
# try to access already generated content
try_files $uri @wkaliszu;
}
location / {
# reverse proxy to the application
[...]
}
location @wkaliszu {
# reverse proxy to the application
[...]
}
}
Сервер был перенесен и теперь использует HAPproxy для балансировки нагрузки, который не является веб-сервером и не поддерживает эту функцию. Теперь динамическое создание программного обеспечения выполняется каждый раз, когда клиент пытается получить доступ к ресурсу, что намного медленнее и расходует ресурсы. Было бы хорошо, если бы он мог использовать следующий бэкэнд, если бы первый (простой веб-сервер кеширования статических файлов) вышел из строя с ошибкой 404, но я не могу найти способ сделать это простым способом. Перенаправление /thumb
в NginX, который пытается прочитать статический файл и снова перезаписывает HAproxy с новым заголовком HTTP, мне приходит только в голову, но я бы хотел найти что-то получше.
Бэкэнды HAProxy либо работают, либо опускаются (или находятся на пути к подъему / падению).
Существуют различные способы проверить работоспособность серверной части, но я не знаю ни одного, обеспечивающего отслеживание на основе запроса. Как только запрос не выполняется, этот бэкэнд будет помечен как неработающий или будет отказывать (на пути к тому, чтобы считаться отключенным).
Это совершенно другая логика, чем ваша установка Nginx, которая маршрутизировала запросы для каждого запроса.
Я вижу здесь несколько вариантов:
Кеширование прокси
В HAProxy вы должны использовать ACL для маршрутизации запросов статического контента к определенному бэкэнду. Эти внутренние узлы будут запускать nginx с кеширующим прокси. Если бы у nginx был файл в кеше, он бы просто обслужил его. Если нет, он позвонит в ваш бэкэнд.
Используйте серверы приложений для статического содержимого
Если ваши серверы приложений эффективно обслуживают статический контент, возможно, вам не потребуется разделять запрос в haproxy. Просто отправьте все запросы в серверную часть вашего приложения. Встраивайте в них логику, чтобы обслуживать статический контент, если он доступен, а если нет, отправлять запрос в бэкэнд.
Вариант CDN
Если вы можете использовать выделенный домен для статического контента, вы можете использовать CDN. В CDN вы просто указываете исходный URL-адрес узлов вашего приложения. Затем вы можете управлять кешированием на уровне CDN. Это похоже на кеширование Nginx выше, за исключением того, что провайдер CDN обрабатывает его за вас.