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-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/161
,Tc
值為 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
,那麼請考慮禁用它,因為潛在的傳輸成本節省可能會被成本所抵消。