Как повторно отправить запрос с помощью 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. 

Важно протестировать обновленную конфигурацию на тестовом окружении, чтобы удостовериться, что она работает так, как вы ожидаете.
У вас здесь несколько вопросов <br/> <blockquote>Я добился только такого поведения. Клиент отправляет запрос, получает ошибку и если он повторно отправит запрос, то идет редирект на резерв. А вот чтоб автоматом, сразу, без дополнительных запросов - не получается</blockquote> <br/> нет, клиент должен сделать еще один реквест - на первый он уже получил 503 <br/> <blockquote>The HTTP protocol is transaction-driven. This means that each request will lead to one and only one response</blockquote> <br/> <br/> и второй, немного иной по своей сути <br/> <blockquote>Можно ли с помощью хапрокси, сделать так, чтобы тот же запрос на котором ответ 503, автоматически перенаправлялся на резервный без полного переключения траффика на резерв?</blockquote> <br/> Немного непонятно, ваш способ который вы упомянули работает без полного переключения трафика? Если нет - можно попробовать балансировку куками <a href="https://www.haproxy.com/documentation/haproxy-configuration-tutorials/session-persistence/" rel="nofollow">https://www.haproxy.com/documentation/haproxy-conf...</a> <br/> То есть работать без настройки "бэкап" сервера, а просто в случае ошибки сетить куку server2 и снимать ее на стороне сервера, а без куки направлять на server1
Похожие вопросы