Haproxy

HAproxy 簡單的反向代理很慢

  • March 6, 2018

我目前正在設置一個 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-Bit
  • 所有機器上的 OpenVPN 版本 2.4.4
  • HAproxy 版本 1.7.9
  • OpenVPN 以 TCP 模式執行
  • Jenkins 的 HAproxy 後端配置取自Jenkins 文件,但如前所述,裸靜態 HTML 內容 Web 伺服器和 REST API Web 服務存在相同的問題。

這是訪問 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 的情況下對此進行了測試。結果是完全一樣的。

您的日誌沒有包含足夠的資訊來解釋 5 分鐘的等待——它跨越不到 2 秒——但這裡是跳出來的:

option http-server-close

這不適用於 WAN 連結另一端的後端。如果您確實需要此功能,則它需要位於後端伺服器延遲極低(例如,本地)的 HAProxy 上。

Tc請注意計時器值中的大量抖動。這是日誌欄位中的第三個值,如下所示:

Tq/Tw/Tc/Tr/Tt

因此,在第一個條目中0/0/13/134/161Tc值為 13 毫秒。 Tc是建立與後端的連接所需的時間,所以我們在這裡看到的是,你的往返抖動幾乎是失控的,在一種情況下會跳到這個值的近三倍。假設這不是由後端伺服器上的資源不足引起的,這很可能是在 TCP 模式下使用 OpenVPN 的結果——可能但不一定表明一些封包遺失。

您在 TCP (OpenVPN) 內部建立 TCP (HTTP) 隧道,這通常適用於非互動式應用程序和抖動不重要的應用程序,但並非如此。(例如,請參閱*Why TCP over TCP is a Bad Idea*來討論一種潛在的崩潰場景,儘管沒有充分的理由完全避免在乾淨的網路上進行這種配置。)通過我認為 OpenVPN 沒有錯, TCP 隧道沒有與 UDP 隧道相同的一致延遲。通過隧道 ping,您應該會看到這種抖動傳遞給 ping 響應時間。

將隧道更改為 UDP,問題應該會消失……但請注意,這種抖動的重要性和性能影響——假設我是正確的,它是使用 TCP 隧道的副作用——可能被使用誇大了option http-server-close,要求每個請求在 HAProxy 和後端之間建立新的連接。

如果您的 OpenVPN 隧道是使用 壓縮的comp-lzo,那麼請考慮禁用它,因為潛在的傳輸成本節省可能會被成本所抵消。

引用自:https://serverfault.com/questions/899018