В настоящее время я настраиваю машину HAproxy, которая будет работать как обратный прокси для пары веб-сайтов. Поскольку разные машины физически не соединены, я использую OpenVPN для создания VPN между машинами.
Технически все работает. Однако моя проблема в том, что запросы, которые я передаю через прокси, чрезвычайно медленные. В конце концов я получаю полный ответ(ы), но требуется до 5 минут, чтобы получить что-то вроде панели мониторинга Jenkins.
Я пробовал простую статическую HTML-страницу, обслуживаемую через NGINX, а также некоторые REST API, реализованные в Go, — результат всегда один и тот же: в конечном итоге я получаю данные, но это занимает невероятно много времени.
Вот моя конфигурация HAproxy:
global
log /var/run/log local0 info
log /var/run/log local0 notice
daemon
maxconn 8000
tune.ssl.default-dh-param 2048
user nobody
group nobody
defaults
log global
option httplog
option dontlognull
mode http
timeout connect 5s
timeout client 1min
timeout server 1min
option forwardfor
option http-server-close
errorfile 400 /usr/local/etc/haproxy/errorfiles/400.http
errorfile 403 /usr/local/etc/haproxy/errorfiles/403.http
errorfile 408 /usr/local/etc/haproxy/errorfiles/408.http
errorfile 500 /usr/local/etc/haproxy/errorfiles/500.http
errorfile 502 /usr/local/etc/haproxy/errorfiles/502.http
errorfile 503 /usr/local/etc/haproxy/errorfiles/503.http
errorfile 504 /usr/local/etc/haproxy/errorfiles/504.http
frontend http-in
bind *:80
bind *:443 ssl crt /usr/local/etc/haproxy/certs/foo.my.org.pem
mode http
use_backend jenkins if { hdr(host) -i foo.my.org }
use_backend test if { hdr(host) -i bar.my.org }
default_backend test
backend jenkins
server jenkins1 <vpn_ip>:8180
mode http
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
reqrep ^([^\ :]*)\ /(.*) \1\ /\2
acl response-is-redirect res.hdr(Location) -m found
rspirep ^Location:\ (http)://<vpn_ip>:8180/(.*) Location:\ https://foo.my.org:443/\2 if response-is-redirect
backend test
server web01 <vpn_ip>:80
Дополнительная информация:
- Все задействованные машины расположены в центрах обработки данных и имеют подключение к Интернету 1G/1G.
- На всех машинах установлена FreeBSD 11 64-Bit.
- OpenVPN версии 2.4.4 на всех машинах
- HAproxy версии 1.7.9
- OpenVPN работает в режиме TCP
- Конфигурация бэкэнда HAproxy для Jenkins взята изДокументация ДженкинсаНо, как уже упоминалось, та же проблема существует и с веб-сервером с чистым статическим HTML-контентом, и с веб-сервисом REST API.
А вот лог HAproxy при доступе к сайту Jenkins:
Feb 27 01:32:24 hostname haproxy[5539]: 213.144.130.227:60243 [27/Feb/2018:01:32:24.093] http-in~ jenkins/jenkins1 0/0/13/134/161 302 153 - - ---- 5/5/0/0/0 0/0 "GET /jenkins HTTP/1.1"
Feb 27 01:32:24 hostname haproxy[5539]: 213.144.130.227:19404 [27/Feb/2018:01:32:24.255] http-in~ jenkins/jenkins1 0/0/25/174/212 200 4492 - - ---- 5/5/0/0/0 0/0 "GET /jenkins/ HTTP/1.1"
Feb 27 01:32:25 hostname haproxy[5539]: 213.144.130.227:16321 [27/Feb/2018:01:32:25.330] http-in~ jenkins/jenkins1 0/0/13/30/54 200 8560 - - ---- 6/6/4/4/0 0/0 "GET /jenkins/static/aeed77bb/scripts/yui/datasource/datasource-min.js HTTP/1.1"
Feb 27 01:32:25 hostname haproxy[5539]: 213.144.130.227:54637 [27/Feb/2018:01:32:25.330] http-in~ jenkins/jenkins1 0/0/27/29/58 200 7585 - - ---- 6/6/3/4/0 0/0 "GET /jenkins/static/aeed77bb/scripts/yui/autocomplete/autocomplete-min.js HTTP/1.1"Feb 27 01:32:25 hostname haproxy[5539]: 213.144.130.227:59247 [27/Feb/2018:01:32:25.361] http-in~ jenkins/jenkins1 0/0/25/16/51 200 9602 - - ---- 6/6/2/3/0 0/0 "GET /jenkins/static/aeed77bb/jsbundles/page-init.js HTTP/1.1"
Feb 27 01:32:25 hostname haproxy[5539]: 213.144.130.227:40637 [27/Feb/2018:01:32:25.332] http-in~ jenkins/jenkins1 0/0/38/18/81 200 16212 - - ---- 6/6/1/1/0 0/0 "GET /jenkins/static/aeed77bb/scripts/yui/menu/menu-min.js HTTP/1.1"
Feb 27 01:32:25 hostname haproxy[5539]: 213.144.130.227:10976 [27/Feb/2018:01:32:25.333] http-in~ jenkins/jenkins1 0/0/37/30/95 200 29110 - - ---- 6/6/0/0/0 0/0 "GET /jenkins/static/aeed77bb/scripts/hudson-behavior.js HTTP/1.1"
Больше ничего в лог-файлах не вижу. Никаких ошибок или чего-то подобного.
Может ли это быть связано с OpenVPN?
Редактировать 1:В то же время я протестировал это без OpenVPN, напрямую используя публичный IP-адрес веб-сервера в конфигурации HAproxy. Результат точно такой же.
решение1
В вашем журнале недостаточно информации, чтобы объяснить 5-минутное ожидание — оно длится менее 2 секунд — но вот что бросается в глаза:
option http-server-close
Это не подходит для бэкенда на другой стороне WAN-соединения. Если вам действительно нужна эта функция, она должна быть на HAProxy с чрезвычайно низкой задержкой (например, локальной) для бэкенд-сервера.
Обратите внимание на большое количество колебаний в Tc
значениях таймера. Это третье значение в поле журнала, которое выглядит так:
Tq/Tw/Tc/Tr/Tt
Итак, в первой записи, 0/0/13/134/161
значение Tc
равно 13 мс. Tc
— это время, необходимое для установления соединения с бэкендом, поэтому мы видим, что ваш джиттер круговой задержки практически вышел из-под контроля, подскочив в одном случае почти в три раза от этого значения. Если предположить, что это не вызвано недостатком ресурсов на бэкенд-сервере, то это, скорее всего, следствие использования OpenVPN в режиме TCP — возможно, но не обязательно, что указывает на некоторую потерю пакетов.
Вы туннелируете TCP (HTTP) внутри TCP (OpenVPN), что обычно подходит для неинтерактивных приложений и приложений, где джиттер не важен, но не в других случаях. (См., например,Почему TCP через TCP — плохая идеядля обсуждения одного из возможных сценариев сбоя, хотя это не достаточная причина, чтобы полностью избегать этой конфигурации в чистой сети.) По причине того, что, как я предполагаю, не является ошибкой OpenVPN, туннели TCP не имеют такой же постоянной задержки, как туннели UDP. Пингуйте через туннель, и вы должны увидеть этот джиттер, привнесенный во время ответа пинга.
Измените туннель на UDP, и проблема должна исчезнуть... но учтите, что значимость и влияние этого дрожания на производительность (если я прав, что это побочный эффект использования туннеля TCP) вероятно преувеличены из-за использования option http-server-close
, которое требует, чтобы каждый запрос устанавливал новое соединение между HAProxy и бэкэндом.
Если ваши туннели OpenVPN сжимаются с помощью comp-lzo
, то рассмотрите возможность отключения и этого, поскольку потенциальная экономия на транспорте может быть перевешена накладными расходами.
решение2
Оказалось, что проблема была в конфигурации брандмауэра/NAT.
Однако, если кто-то столкнется с этой проблемой, в сообществе HAproxy есть дополнительная помощь:https://discourse.haproxy.org/t/reverse-proxy-very-slow-page-load/2172