我目前正在设置一台 HAproxy 机器作为几个网站的反向代理。由于不同的机器没有物理连接,我使用 OpenVPN 在机器之间创建 VPN。
从技术上讲,一切都正常。但是,我的问题是,通过代理发送的请求非常慢。我最终得到了完整的响应,但需要最多 5 分钟才能收到类似 Jenkins 仪表板的内容。
我尝试了通过 NGINX 提供的简单静态 HTML 页面以及用 go 实现的一些 REST API - 结果总是一样的:我最终获得了数据,但这花费了大量的时间。
这是我的 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 位
- 所有机器上均安装 OpenVPN 2.4.4 版本
- HAproxy 版本 1.7.9
- OpenVPN以TCP模式运行
- Jenkins 的 HAproxy 后端配置取自Jenkins 文档但如上所述,裸静态 HTML 内容网络服务器和 REST API 网络服务也存在同样的问题。
以下是访问 Jenkins 站点时的一些 HAproxy 日志:
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:同时,我通过在 HAproxy 配置中直接使用 Web 服务器的公共 IP 地址来测试此操作,而无需使用 OpenVPN。结果完全相同。
答案1
您的日志没有包含足够的信息来解释 5 分钟的等待时间 — — 它持续的时间不到 2 秒 — — 但以下是显而易见的信息:
option http-server-close
这不适用于 WAN 链接另一端的后端。如果您确实需要此功能,则需要将其放在与后端服务器具有极低延迟(例如本地)的 HAProxy 上。
请注意计时器值中存在大量抖动Tc
。这是日志字段中的第三个值,如下所示:
Tq/Tw/Tc/Tr/Tt
因此,在第一个条目中0/0/13/134/161
,该Tc
值为 13 毫秒。 Tc
这是建立与后端的连接所需的时间,因此我们在这里看到的是您的往返抖动几乎失控,在一种情况下跳升至该值的近三倍。假设这不是由后端服务器资源不足引起的,这很可能是在 TCP 模式下使用 OpenVPN 的结果——可能(但不一定)表示存在一些数据包丢失。
您正在 TCP(OpenVPN)内建立 TCP(HTTP)隧道,这通常适用于非交互式应用程序和抖动不重要的应用程序,但其他情况则不然。(例如,参见为什么 TCP over TCP 是一个坏主意讨论其中一种潜在的崩溃情况,但这并不是在干净的网络上完全避免这种配置的充分理由。)我认为这不是 OpenVPN 的错,TCP 隧道的延迟与 UDP 隧道不同。通过隧道进行 ping,您应该会看到这种抖动影响了 ping 响应时间。
将隧道更改为 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