HAproxy简单反向代理非常慢

HAproxy简单反向代理非常慢

我目前正在设置一台 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

相关内容