現在、いくつかの Web サイトのリバース プロキシとして機能する HAproxy マシンを設定しています。異なるマシンは物理的に接続されていないため、OpenVPN を使用してマシン間の VPN を作成しています。
技術的にはすべて正常に動作しています。ただし、プロキシを介してパイプするリクエストが非常に遅いという問題があります。最終的には完全な応答が得られますが、Jenkins ダッシュボードのようなものを受け取るまでに最大 5 分かかります。
私は、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 コンテンツ 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
。これは、ログ フィールドの 3 番目の値で、次のようになります。
Tq/Tw/Tc/Tr/Tt
したがって、最初のエントリでは0/0/13/134/161
、Tc
値は 13 ミリ秒です。は Tc
バックエンドへの接続を確立するために必要な時間です。したがって、ここでわかるのは、ラウンドトリップ ジッターがほぼ制御不能であり、あるケースではこの値のほぼ 3 倍に跳ね上がっているということです。これがバックエンド サーバーのリソース不足によって発生したのではないと仮定すると、これは OpenVPN を TCP モードで使用した結果である可能性が高く、パケット損失を示している可能性がありますが、必ずしもそうとは限りません。
TCP (HTTP) を TCP (OpenVPN) 内でトンネリングしています。これは、非対話型アプリケーションやジッターが重要でないアプリケーションでは通常は問題ありませんが、それ以外の場合は問題があります。(たとえば、TCP over TCP がなぜ悪いアイデアなのか潜在的なメルトダウン シナリオの 1 つについて議論するために、この設定をクリーンなネットワークで完全に避ける十分な理由ではありませんが、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