HAProxy 2.0 — повтор некоторых запросов на основе URL

HAProxy 2.0 — повтор некоторых запросов на основе URL

У меня установлен HAProxy версии 2.0.14, и я ищу необычный вариант использования, который мне пока не удалось правильно настроить.

По сути, у меня есть фронтенд, который слушает порт, и два бэкенд-сервера. После запуска сеанса используются куки, поэтому сеанс привязан к определенному бэкенд-серверу и не может быть передан другому серверу. Для этого я использую ключевые слова stick-tableи stick onскрипт LUA, чтобы получить требуемое значение из запросов.

Однако если при поступлении первого запроса выбранный внутренний сервер не отвечает вовремя, нам следует выполнить переключение на другой, поскольку на этом этапе cookie-файл еще не установлен.

На данный момент у меня следующая конфигурация:

global
   log 127.0.0.1 len 10000 local2 debug
   chroot /var/lib/haproxy
   user haproxy
   group haproxy
   daemon
   lua-load /opt/LUA/myparser.lua

   stats socket /etc/haproxy/haproxysock level admin

defaults
   log global
   option httplog
   option dontlognull
   mode http
   timeout connect 5000
   timeout client 50000
   timeout server 50000
   log-format "Client IP:port = [%ci:%cp], Start Time = [%tr], Frontend Name = [%ft], Backend Name = [%b], Backend Server = [%s], Time to receive full request = [%TR ms], Response time = [%Tr ms], Status Code = [%ST], Bytes Read = [%B]"

frontend chatgw_front
   bind *:8776

   option http-buffer-request
   declare capture request len 40000
   http-request capture req.body id 0
   http-request capture req.hdrs len 2048

   http-request track-sc0 src table my_back
   use_backend my_back

backend my_back
   balance roundrobin

   stick-table type string len 32 size 30k expire 30m
   stick on "lua.parseId" table my_back

   server server1 x.x.x.1:8080 check
   server server2 x.x.x.2.8080 check

Это делает следующее: если выбранный бэкенд-сервер не отвечает в течение 50 секунд, он выдает клиенту HTTP 504 Gateway Timeout. Вместо этого мне нужно, если это первый запрос в сеансе, то (и только тогда) переключение на другой бэкенд-сервер. Мы можем сказать, что это первый запрос, основываясь на URL.

Я попробовал изменить бэкэнд следующим образом:

backend my_back
   balance roundrobin

   stick-table type string len 32 size 30k expire 30m
   stick on "lua.parseId" table my_back

# Check if this is "init" request: in this case URL contains "/init"
   acl is_init path_sub /init

# In case of "init" request, enable redispatch to other backend server in case failure
   option redispatch if is_init

# In case of other requests (not "init"), we are already tied to a selected backend server due to session cookie, so disable redispatch
   no option redispatch if !is_init

   server server1 x.x.x.1:8080 check
   server server2 x.x.x.2.8080 check

Однако я получил точно такое же поведение. Поэтому я попробовал добавить "retry-on":

backend my_back
   balance roundrobin

   stick-table type string len 32 size 30k expire 30m
   stick on "lua.parseId" table my_back

   acl is_init path_sub /init

   option redispatch if is_init

   no option redispatch if !is_init

   retry-on conn-failure empty-response response-timeout

   server server1 x.x.x.1:8080 check
   server server2 x.x.x.2.8080 check

Теперь все по-другому: он попытался отправить первоначальный запрос 4 раза на один и тот же сервер, а затем вернул HTTP 504. Затем он получил следующий запрос (который не является «init», поэтому не должен привязываться к выбранному внутреннему серверу), и вместо этого он был отправлен на другой сервер.

В общем, моя проблема: как реализовать отказоустойчивость только на первом запросе? Любой другой запрос должен всегда придерживаться выбранного бэкенд-сервера.

Связанный контент