我目前正在設定一台 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 後端設定取自提供的詹金斯文檔但如同前面所提到的,裸靜態 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:同時,我在沒有 OpenVPN 的情況下透過直接使用 HAproxy 配置中的 Web 伺服器的公用 IP 位址進行了測試。結果是完全一樣的。
答案1
您的日誌沒有包含足夠的資訊來解釋 5 分鐘的等待 - 它的時間跨度不到 2 秒 - 但以下是跳出的內容:
option http-server-close
這對於 WAN 連結另一側的後端來說是不合適的。如果您確實需要此功能,則它需要位於後端伺服器延遲極低(例如本機)的 HAProxy 上。
請注意計時器值中存在大量抖動Tc
。這是日誌欄位中的第三個值,如下所示:
Tq/Tw/Tc/Tr/Tt
因此,在第一個條目中0/0/13/134/161
,Tc
的值為 13 ms。 Tc
是建立與後端的連接所需的時間,因此我們在這裡看到的是,您的往返抖動幾乎失去了控制,在一種情況下跳到了該值的近三倍。假設這不是由後端伺服器上的資源不足引起的,這很可能是在 TCP 模式下使用 OpenVPN 的結果 - 可能但不一定表示存在一些封包遺失。
您在 TCP (OpenVPN) 內部建立 TCP (HTTP) 隧道,這通常適用於非互動式應用程式和抖動不重要的應用程序,但其他情況則不然。 (例如,參見為什麼 TCP over TCP 是個壞主意討論一種潛在的崩潰場景,儘管沒有充分的理由在乾淨的網路上完全避免這種配置。透過隧道進行 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