私は過去数日間頭を悩ませており、次の問題の解決策を考え出そうとしています:
私たちのデータセンターでは、BigIPハードウェア上で実行されているF5を使用しています。F5は、全国のさまざまなオフィスの場所にあるクライアントマシンからのHTTPSリクエストの単一の入口ポイントとして機能します。 F5はTLSを終了し、すべての要求を2つのTraefikロードバランサーに転送します。2つのTraefikロードバランサーは、要求をさまざまなサービスインスタンスにルーティングします(TraefikノードはRed Hat EnterpriseのDockerで実行されていますが、これは私の問題とは無関係です)。スループット、CPU、メモリの観点から見ると、これら3つのネットワークコンポーネントは、十分な容量を確保して、要求とトラフィックの量を処理する能力を超えています。
ただし、特に高負荷時にクライアントが行うHTTP(S)リクエストで1000ミリ秒の遅延が頻繁に発生することに気付きました。次の根本原因まで問題を追跡しました。
明らかに、これらの1000ミリ秒の遅延は絶対に許容できません。したがって、これまでに次のソリューションを検討しました。
#1はバンドエイドなので破棄します。遅延はまだ発生していますが、少し目立ちません。いずれにしても、#3は何の効果もありません。#4はシステムを機能させない可能性があります。葉っぱ #2 と#5。
しかし、私が何十もの投稿や技術記事を読んだ後に私が学んだことを基にすると、どちらも最終的にはこれらの「衝突」の可能性を(== --- ==)減らすだけです。送信側F5が最終的に(疑似)ランダムに選択するのは、fin_timeout設定がどれだけ短いかに関係なく、ターゲットのTraefikホストでTIME_WAIT状態にまだ存在しているエフェメラルポート、ソースIP、およびターゲットポートの組み合わせをランダムに選択するためです(とにかく数秒の範囲に留まる必要があります)?衝突の可能性を減らすだけでなく、なくすことはしません。
私のすべての調査の後、そして巨大なWebアプリケーションの時代に、この問題がWeb(および利用可能な解決策)でこれ以上議論されていないことに本当に驚いています。衝突の発生をゼロに近づけるTCPの土地により良い、より体系的な解決策があるかどうかについてのあなたの考えと考えを本当に感謝します。古い接続がTIME_WAIT状態であっても、Traefikホストが新しい接続をすぐに受け入れることができるTCP構成に沿って考えています。しかし、今のところ、それを見つけることはできません。
ランダムな考えとポイント:
更新:Per The Star Experiment 、net.ipv4.tcp_fin_timeout設定はTIME_WAIT状態には影響せず、FIN_WAIT_2状態にのみ影響します。そして Samir Jafferali に従って、Linuxシステム(Red Hat Linuxを含む)では、TIME_WAIT期間はソースコードにハードコードされており、構成できません。ソースによるとBSDでは、それは設定可能ですが、私はこれを確認していません。
私たちのデータセンターでは、BigIPハードウェア上で動作するF5が動作しますassingleingress point HTTPSリクエストに対してさまざまなクライアントマシンから全国のオフィスの場所。
この単一のポイント(フロントエンド)が接続をバックエンドに渡すときに単一のままである場合、なぜ問題が発生するのでしょうか。特に接続の強度が「おそらく1秒あたり100以上」の場合。
あなたの設定は基本的に、カーディナリティが高い1つのセットを、カーディナリティが大幅に低い別のセットに絞り込んでいます。
最終的には、これらの「衝突」の可能性を減らすだけです
これは、パケット交換ネットワークがどのように機能するかに基づいて行われます。たとえば、イーサネットレベルでは衝突も発生します。ランダム性は避けられず、TCP/IPはそれを処理します。 IPプロトコル自体は、実際にはLANを考慮せずに構築されています(ただし、そこでもうまく機能します)。
したがって、「ソースIPを追加するか、Traefikを複数のポートでリッスンさせる」というのは、かなり合理的な方法です。
さらにIPアドレスを追加するのが最も簡単な方法だと思いますが、外部リクエストごとに新しいIPアドレスを作成する代わりに、F5ノードとTraefikノード間のTCP接続の再利用を検討することを検討しましたか?
F5がそれをどのようにサポートするかはわかりませんが、F5ノードとTraefikノード間でhttp2に切り替えるだけの簡単なものでしょう。 https://developers.google.com/web/fundamentals/performance/http2#one_connection_per_Origin を参照してください
結局のところwas結局のところ、この問題に対する非常に単純な解決策です。これは、Traefikベンダーとしばらくの間作業した後でわかったものです。また、DockerでTraefikを実行しているという事実doesが重要であることもわかります。問題と解決策は私たちの設定に非常に固有ですが、他の人が同じ問題に遭遇した場合に備えて、ここで文書化したいと思います。それにもかかわらず、インスタンスIDの衝突が実際の問題であるため、これはnotを無効にします。
要するに、すべてのTraefikインスタンスは、Docker Swarmクラスターで実行されているホスト制約付きコンテナー(つまり、特定のホストに関連付けられている)として構成されます。 Traefikインスタンスは、Docker Swarm参加者ではないF5から到達可能になるように、ホストレベルでポートを公開する必要があります。これらの公開されたポートは、ingressモードで構成されていましたが、これは不要なだけでなく(Docker Swarm入力ネットワークを介してトラフィックをルーティングする必要もありません)、ドロップ/無視されたSYNパケットの原因。ポートモードをHostに切り替えると、遅延はなくなりました。
前:
ports:
- target: 8080
published: 8080
protocol: tcp
mode: ingress
後:
ports:
- target: 8080
published: 8080
protocol: tcp
mode: Host