Я пытался протестировать установку, которая выглядит так:
Веб-сайт: Http GET Request -> Nginx -> HAProxy -> .Net приложение
Я разместил 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 просто говорит «Плохой запрос». Как ни странно, я не вижу ошибок в моем файле журнала.
Вот пример из файла журнала:
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 запрос за раз.
Я столкнулся с той же проблемой, и мне потребовалось время, чтобы понять, почему это происходит.
Моя среда состоит из 1 HAproxy и 2 nginx в качестве бэкэнда с nodejs в качестве CGI-подобного.
Основная причина зависит от того, как HAproxy создает HTTP-запрос. По умолчанию HAproxy не включает заголовок хоста в запрос, поэтому вам нужно добавить его вручную, иначе nginx вернет 400 по умолчанию, а HAproxy отметит его как неработоспособный.
Пример ниже:
Конфигурация проверки работоспособности HAproxy:
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:
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
Если вы запустите это сразу после получения ошибки «Плохой запрос», он должен показать вам, что именно 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
config вместо этого
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. Например:
listen stats
bind 10.10.10.200:80
mode http
stats enable
stats hide-version
stats uri /
option httpclose
stats auth username:password