Как повторно отправить запрос с помощью HAPROXY?

У меня есть два хоста, настроенные в HAProxy: основной, на который поступает весь трафик, и резервный. Иногда основной хост возвращает ошибку 503 для некоторых запросов. Резервный хост активируется через 3 секунды, если основной становится недоступным. Возможен ли в HAProxy настройка, которая позволит автоматически перенаправлять запросы, получившие ответ 503, на резервный хост без полного переключения трафика на него? 

Я пытался реализовать это с помощью надстройки LUA, но достиг лишь такого поведения: клиент отправляет запрос, получает ошибку, и при повторной отправке запрос перенаправляется на резервный хост. Однако я хочу, чтобы это происходило автоматически, без необходимости дополнительных запросов. У меня возникли трудности, так как некоторые методы не поддерживает LUA, а другие — сам HAProxy. 

Можете ли вы поделиться опытом или подсказать, как это можно реализовать? 

Вот моя текущая конфигурация: 

```
global 
    maxconn 100 
    log stdout local0 info 
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners 
    stats timeout 30s 

defaults 
    retries 2 
    timeout client 30m 
    timeout connect 4s 
    timeout server 30m 
    timeout check 5s 

frontend stats 
    mode http 
    bind *:8080 
    stats enable 
    stats uri /stats 
    stats refresh 5s 

listen data 
    log global 
    mode http 
    option httplog 
    option httpchk /**/api/4_5/rs/status 
    bind *:8081 
    balance roundrobin 
    option redispatch 
    retries 3 
    retry-on 503 
    http-send-name-header Host 
    server server1 server.ru:** 
    server server2 server.ru:** check backup 
```
  • 31 октября 2024 г. 14:43
Ответы на вопрос 2
Для настройки HAProxy так, чтобы он автоматически перенаправлял запросы на резервный хост в случае получения ошибки 503 от основного хоста, можно использовать параметр `option redispatch` в сочетании с настройками `retry-on`. Ваше текущее решение частично правильно, однако вам нужно немного изменить его, чтобы достичь желаемого поведения.

Вот несколько шагов и рекомендаций, которые могут помочь в реализации такого функционала:

1. **Используйте уникальный `timeout` для retries**:
   Убедитесь, что у вас установлен подходящий таймаут для `timeout connect`, так как пытаетесь обработать 503, возможно стоит установить его более коротким. 

2. **Используйте `retry-on`**:
   В вашей конфигурации уже используется `retry-on 503`, что позволяет HAProxy автоматически повторять запрос на другом сервере в случае ошибки 503. Однако это будет работать только если HAProxy не завершит соединение клиентом до того, как удастся перенаправить запрос.

3. **Настройка `http-response`**:
   Добавьте `http-response` директиву для обработки 503 ответов.
   
4. **Конфигурация `listen` блока**:
   Убедитесь, что балансировщик настроен правильно, чтобы поддерживать автоматическое перенаправление запросов, при помощи опции `httpchk`.

Вот обновленная версия вашей конфигурации, основанной на этих рекомендациях:

```haproxy
global 
    maxconn 100 
    log stdout local0 info 
    stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners 
    stats timeout 30s 

defaults 
    retries 2 
    timeout client 30m 
    timeout connect 2s 
    timeout server 30m 
    timeout check 5s 

frontend stats 
    mode http 
    bind *:8080 
    stats enable 
    stats uri /stats 
    stats refresh 5s 

listen data 
    log global 
    mode http 
    option httplog 
    option httpchk /**/api/4_5/rs/status 
    bind *:8081 
    balance roundrobin 
    option redispatch 
    retries 3 
    retry-on 503 
    http-send-name-header Host 
    http-request set-header X-Forwarded-For %[src]  # добавить IP клиента
    http-response set-header X-Forwarded-Host %[http.host]
    
    server server1 server.ru:port check
    server server2 server.ru:port check backup
```

Обратите внимание на изменения в таймаутах, и как настроены `http-request` и `http-response`. Вы также можете добавить дополнительные условия, если вам нужно будет обработать другие коды ошибок.

Если даже после этого проблемы будут существовать, вам может понадобиться более низкоуровневый механизм, например использование Lua-скриптов. Однако это обычно не требуется, если правильно использовать возможности самого HAProxy. 

Важно протестировать обновленную конфигурацию на тестовом окружении, чтобы удостовериться, что она работает так, как вы ожидаете.
У вас здесь несколько вопросов 
Я добился только такого поведения. Клиент отправляет запрос, получает ошибку и если он повторно отправит запрос, то идет редирект на резерв. А вот чтоб автоматом, сразу, без дополнительных запросов - не получается

нет, клиент должен сделать еще один реквест - на первый он уже получил 503
The HTTP protocol is transaction-driven. This means that each request will lead to one and only one response


и второй, немного иной по своей сути
Можно ли с помощью хапрокси, сделать так, чтобы тот же запрос на котором ответ 503, автоматически перенаправлялся на резервный без полного переключения траффика на резерв?

Немного непонятно, ваш способ который вы упомянули работает без полного переключения трафика? Если нет - можно попробовать балансировку куками https://www.haproxy.com/documentation/haproxy-conf...
То есть работать без настройки "бэкап" сервера, а просто в случае ошибки сетить куку server2 и снимать ее на стороне сервера, а без куки направлять на server1
Похожие вопросы