HAProxy возвращает неверный запрос (неверный хост), казалось бы, без причины
Я пытался проверить настройки, которые выглядят так:
Веб-сайт: HETP GET Request -> Nginx -> HAProxy -> .Net application
Я разместил Nginx и HAProxy на одной машине Debian. Однако HAProxy постоянно возвращает "Bad Request (Invalid Host)". Я определил, что HAProxy виноват, сначала отправив запрос непосредственно с веб-сайта в приложение.Net, которое работает. Наличие ссылки Nginx на приложение.Net также работает. Однако, когда я пытаюсь проверить это с HAProxy на месте, я начинаю получать ошибку. Не имеет значения, действительно ли приложение.Net работает за HAProxy, я всегда получаю сообщение об ошибке.
Пример сообщения, которое я пытаюсь отправить: http://192.168.7.119:81/a:diff1
, Ожидаемый ответ - изображение JPG. Кажется, это работает нормально, когда отправляется на что-либо, кроме HAProxy (Apache, Nginx, приложение), но HAProxy просто говорит "Bad Request". Как ни странно, я не вижу никаких ошибок в моем файле журнала.
Вот пример из файла журнала:
Feb 2 15:10:08 companyDebian haproxy[5566]: 192.168.7.114:51105 [02/Feb/2015:15:10:08.415] renderfarm renderfarm/renderA 0/0/0/1/1 400 212 - - ---- 1/1/0/1/0 0/0 "GET /a:diff1 HTTP/1.1"
Feb 2 15:10:08 companyDebian haproxy[5566]: 192.168.7.114:51105 [02/Feb/2015:15:10:08.417] renderfarm renderfarm/renderA 73/0/0/4/77 400 212 - - ---- 1/1/0/1/0 0/0 "GET /favicon.ico HTTP/1.1"
Мой конфигурационный файл выглядит так:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL).
ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen renderfarm
bind 192.168.7.119:81
mode http
balance roundrobin
server renderA 192.168.7.114:40000 maxconn 1
У меня нет предыдущего опыта работы с HAProxy, и я использую его, потому что он был рекомендован мне. Поэтому я не знаю, какие еще шаги я могу предпринять, чтобы решить эту проблему. В руководстве по настройке упоминаются различные параметры, которые вы можете установить, такие как tune.bufsize и option accept-invalid-http-request, но они не действуют.
Примечание. Идея состоит в том, чтобы добавить больше серверов, на которых запущено приложение, после того, как эта настройка сработает. Каждый сервер действительно может обрабатывать только 1 запрос за раз.
4 ответа
Я столкнулся с той же проблемой и потратил некоторое время, чтобы понять, почему это происходит.
Моя среда сформирована из 1 HAproxy и 2 nginx в качестве бэкэнда с nodejs как CGI-подобный.
Основная причина основана на том, как HAproxy создает HTTP-запрос. По умолчанию HAproxy не включает заголовок узла в запрос, поэтому вам нужно добавить его вручную, иначе nginx вернет 400 по умолчанию, а HAproxy пометит его как нездоровый.
Пример ниже:
Проверка работоспособности HAproxy conf:
option httpchk HEAD / HTTP/1.1
Эквивалентный HTTP-запрос:
tony@calderona:~ $ telnet A.B.C.D 80 Trying A.B.C.D... Connected to A.B.C.D. Escape character is '^]'. HEAD / HTTP/1.1 HTTP/1.1 400 Bad Request Server: nginx/1.10.3 Date: Sun, 10 Dec 2017 09:52:12 GMT Content-Type: text/html Content-Length: 173 Connection: close
Проверка работоспособности HAproxy conf:
option httpchk HEAD / HTTP/1.1\r\nHost:\ www.temporaryworkaround.org
Эквивалентный HTTP-запрос:
tony@calderona:~ $ telnet A.B.C.D 80 Trying A.B.C.D... Connected to A.B.C.D. Escape character is '^]'. HEAD / HTTP/1.1 host: www.temporaryworkaround.org HTTP/1.1 200 OK Server: nginx/1.10.3 Date: Sun, 10 Dec 2017 09:52:24 GMT Content-Type: text/html; charset=utf-8 Content-Length: 10282 Connection: keep-alive
ура
Если вы хотите увидеть точную ошибку HAproxy, вы можете сделать это, используя socat
подключиться к сокету администратора. устанавливать socat
с помощью apt-get install socat
, затем выполните следующее:
echo "show errors" | socat unix-connect:/run/haproxy/admin.sock stdio
Если вы запустите это сразу после получения ошибки "Bad Request", она должна показать вам, что именно HAproxy не понравилось в HTTP-запросе, сделанном клиентом.
ПРИМЕЧАНИЕ. Вышеуказанное работает только при включенном
Unix Socket commands
заHAProxy
, Вам нужно будет добавить одну строку конфигурации вglobal
раздел, чтобы включить это.global stats socket /var/run/haproxy.sock mode 600 level admin
Размещение HAProxy позади Nginx кажется легкомысленным, поскольку и Nginx, или HAProxy могут в одиночку обеспечить функциональность, которая вам, кажется, требуется.
Рассмотрите возможность разбиения раздела прослушивания на frontend
а также backend
разделы с host
или же path_beg
acls и упростите настройку, пока не получите ответ. Также рассмотрите либо исключительно использование forwardfor
с одним сервером или добавлением другого сервера для roundrobin
, Некоторые примеры-
frontend http-in
bind 0.0.0.0:80
acl host_1 hdr(host) -i firstsite.com
acl host_nginx hdr(host) -i secondsite.com
Спаривание спереди и сзади-
use_backend firstsite_redirect if host_1
use_backend nginx if host_nginx
Конфигурация сервера
backend firstsite_redirect
mode http
option forwardfor
server firstserver 192.168.0.2:8080
backend nginx
mode http
balance roundrobin
option httpclose
option forwardfor
cookie SRVNAME insert
server nginx01 192.168.0.3:8080 cookie s1 check
server nginx02 192.168.0.4:8080 cookie s2 check
Если вы хотите перенаправить на основе URL, рассмотрите возможность использования path_beg
в frontend
вместо конфигурации
frontend http-in 0.0.0.0:80
acl docs path_beg /docs
acl phpmyadmin path_beg /phpmyadmin
Возможно, стоит попытаться изменить конфигурацию HAProxy на TCP вместо HTTP. Вы теряете некоторые расширенные параметры балансировки нагрузки, которые предоставляет HTTP (настройка файлов cookie для сохранения и т. Д.), Но, похоже, вы их сейчас не используете.
Вот пример конфигурации, которую я использую с HAProxy для балансировки нагрузки MySQL:
listen mysql-failover
bind 10.10.10.210:3306
mode tcp
option tcplog
option mysql-check user haproxy
server db1 10.10.10.13:3306 check fall 2 inter 1000
server backup 10.10.10.11:3306 check
Обратите внимание, что если вы перейдете на TCP, вы потеряете доступ к встроенной странице статистики HTTP, которую вы можете определить в отдельном операторе прослушивания. Например:
listen stats
bind 10.10.10.200:80
mode http
stats enable
stats hide-version
stats uri /
option httpclose
stats auth username:password