TCPパケットロスソリューション

I.はじめに

        前回の記事TCP パケット損失調査_tingmailang のブログ - CSDN ブログ に引き続き、パケット損失検査は環境およびネットワーク リンク層で確認されています。追跡調査と解決策のブロガーがプロセス全体を追跡できるように、ここで共有します。

2. パケット損失の原因 - オペレーティング システム レベル

        前回の記事では、TCP ハンドシェイクで時折発生するパケット損失を特定しました。O&M は Alibaba Cloud 担当者に連絡して、パケット損失がクラウド プラットフォームに関連しているかどうかを確認しました。Alibaba Cloud がシステム監視を実施したところ、実際に多くのパケット損失現象が発生していることがわかりました。

                                              

        Alibaba Cloud は、kernel-4.19.91-25.1.al7 およびそれ以前のカーネル バージョンでは、アプリケーションが複数の TCP 接続要求を同時に開始すると、大量の TCP パケットが NAT テーブルを通過し、重複したポートを取得する可能性があると説明しました。Conntrack モジュールは、確認フェーズ中にポートが重複していることを検出し、関連する TCP パケットを破棄します。

        iptablesファイアウォールを使用してフィルタリング (フィルター) と NAT ルールを作成でき、すべての Linux ディストリビューションで iptables を使用できます。したがって、NATの重複ポートを取得するLinuxの仕組みによって決まります。

        学生の中には、k8s は隔離されているのではないか、どうやってポートを再利用できるのかと疑問に思う人もいるかもしれません。実際、物理マシンに k8s コンテナがあれば確かに隔離されますが、これでは k8s の意味も失われます。つまり、メモリ ディスクなどの物理マシン上で互いに干渉しやすいリソースを隔離し、単に 1 つの物理マシンを使用するだけです。サービスとしてのマシン。

        運用環境では基本的に 1 つの物理的な機会に十数個のサービスがあり、コア CPU とネットワーク ポートは実際には k8s コンテナ内のサービスによって共有されます。

 

現在のマイクロサービス環境でのリクエスト送信プロセスを要約します。

        ① x サービスはリクエストを送信し、 iptables の NAT テーブルを通じて (データ パケットの) ネットワーク アドレスをIP + Port変換してポートを取得します。

        ②ポートはTCPハンドシェイクパケットを送信し、Linux Conntrackモジュールがセルフチェックして確認します(パケットはnf_conntrack_in()、nf_conntrack_confirm()を経て、作成(新規)と確認(確認)の2段階になります )

        ③リクエストがサービスグリッド1に到達

        ④サービスグリッドはiptables の NAT テーブルを通じて(データパケットの)ネットワークアドレスをIP + Port変換し、ポートを取得し、tcp リンクを確立します。

        ⑤グリッドはTCPハンドシェイクパケットを送信し、Linux Conntrackモジュールは自己チェックと確認を行います(パケットはnf_conntrack_in()、nf_conntrack_confirm()を経由して作成(新規)と確認(確認)の2段階を経ます )

        ⑥サーバーオペレーティングシステムはハンドシェイクリクエストパケットを受信し、iptablesのNATテーブルを通じてポートを取得し、このポートを使用してクライアントグリッドとのTCPリンクを確立します。

        ⑦グリッド 1 はグリッド 2 にデータを転送します

        ⑧ サービスグリッド 2 はリクエストデータを受信し、処理のために y サービスに転送します。

 ここで、今回の問題は 2 番目と 5 番目にあることがわかります。取得ポートが繰り返され、Linux セルフテストが確認され、ハンドシェイクがタイムアウトになり、tcp が再度ハンドシェイクを開始すると、パケットは直接破棄されます。

3. パケットロスソリューション - オペレーティングシステムレベル

         Alibaba Cloud の説明によると、4.19 は順次取得されるため比較的頻繁に取得されます。yum を使用して 5.x 以降にアップグレードしてください。5.X のカーネルはランダムに取得され、ポート重複の頻度は比較的低いです。

        この解決策は確率論的です。ポートのパケット損失が繰り返されるリスクは依然として存在しますが、その頻度は減少します。ただし、Alibaba Cloud は他の最適化を行っています。ポートがパケットを繰り返し損失すると、ただちに TCP に再送信するよう通知するため、遅延は長くなります。ミリ秒レベルまで低減できます。

4. パケットロスソリューション - サービスレベル

        パケットロスはOSやネットワークレベルでは問題ですが、サービスレベルでの最適化の解決策はなく、解決策とは言えないかもしれません。OSのアップグレードと同じですが、パケットロスの頻度は高くなります。可能な限り軽減されます。

        前回の記事の位置づけによれば、パケット損失は基本的に最初のハンドシェイクであるため、新しい TCP 接続の作成を避けて、それらをより再利用できるでしょうか?

        この方法はまだあります。サービスで使用される json シリアル化は、fasterxml.jackson のデフォルトの EAGER_DESERIALIZER_FETCH です。このシリアル化が応答 json を読み取るとき、次の多重化接続が使用されるように、最後の \r\n が読み取られない可能性があります。場合によっては、ダーティ データが見つかることがあります。\r\n接続を閉じて、新しい TCP 接続を作成します。

        FAIL_ON_TRAILING_TOKENS を使用するように変更すると、上記の状況で新しい tcp を減らすことができます。jackson 自体への影響は、逆シリアル化する前に "{json}xxxxx" のような文字列だった場合、追加後に失敗しますが、通常のビジネスでは問題が発生することです。このような異常な JSON はシーンに表示されません。

        もちろん、この変更はパケット損失を直接目的としたものではなく、主に tcp の再利用を目的としているため、影響は考えられます。新しいリンクは避けられず、リンクは常に再利用されるわけではありません。ネットワーク上の理由によるパケット損失に依存します。リンクを再利用するだけなのか、それとも新しいリンクを作成するのか。

V. まとめ

        最後に、TCP ハンドシェイク パケットの損失は、Alibaba Cloud カーネルが TCP リンクを確立するために重複したポートを簡単に取得したことが原因であることが判明し、Linux セルフテストでは、ハンドシェイク パケットが再利用されていることが判明した場合は破棄されることが確認されました。

        解決策は、同じ方法でカーネルをアップグレードし (逐次取得ではなくランダム取得し、ポートが繰り返しパケットを失った場合はすぐに tcp に再送信するように通知します)、サービスは json を使用して FAIL_ON_TRAILING_TOKENS を構成します (新しい tcp リンクを削減します)。

おすすめ

転載: blog.csdn.net/m0_69270256/article/details/126710697