3

Solaris から RH Linux に移行するクライアント/サーバー アプリ (Java) があります。RH での実行を開始してから、レイテンシーに関連するいくつかの問題に気付きました。次のような問題を切り分けることができました。

  • クライアントは 5 つのメッセージ (各 32 バイト) を連続して (同じアプリケーションのタイムスタンプで) サーバーに送信します。
  • サーバーはメッセージをエコーし​​ます。
  • クライアントは応答を受信し、各メッセージの往復時間を出力します。

Solaris では、すべて問題ありません。元のメッセージを送信してから約 80 ミリ秒で、同時に 5 つの応答すべてを受け取ります (クライアントとサーバーは互いに数千マイル離れています。私の ping RTT は 80 ミリ秒で、すべて正常です)。

RH では、最初の 3 つのメッセージは正常にエコーされます (送信後 80 ミリ秒で到着します) が、次の 2 つは 80 ミリ秒後に到着します (合計 160 ミリ秒の RTT)。

パターンは常に同じです。明らかにTCPの問題のように見えました。

私のsolarisボックスでは、以前に2つの特定のオプションを使用してtcpスタックを構成していました。

  1. nagle アルゴリズムをグローバルに無効にする
  2. tcp_deferred_acks_max を 0 に設定します

RH では、nagle をグローバルに無効にすることはできませんが、すべてのアプリのソケット (TCP_NODELAY) で無効にしました。

そこで、(サーバー マシン上で) tcpdump を使い始め、両方の出力を比較しました。

ソラリス:

 22 2.085645    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=111 Ack=106 Win=66672 Len=22    "MSG_1 RCV"
 23 2.085680    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=133 Win=50400 Len=0
 24 2.085908    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=133 Ack=106 Win=66672 Len=22    "MSG_2 RCV"
 25 2.085925    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=155 Win=50400 Len=0
 26 2.086175    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=155 Ack=106 Win=66672 Len=22    "MSG_3 RCV"
 27 2.086192    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=177 Win=50400 Len=0
 28 2.086243    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=106 Ack=177 Win=50400 Len=21    "MSG_1 ECHO"
 29 2.086440    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=177 Ack=106 Win=66672 Len=22    "MSG_4 RCV"
 30 2.086454    server         client          TCP      6006 > 56150 [ACK] Seq=127 Ack=199 Win=50400 Len=0
 31 2.086659    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=127 Ack=199 Win=50400 Len=21    "MSG_2 ECHO"
 32 2.086708    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=199 Ack=106 Win=66672 Len=22    "MSG_5 RCV"
 33 2.086721    server         client          TCP      6006 > 56150 [ACK] Seq=148 Ack=221 Win=50400 Len=0
 34 2.086947    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=148 Ack=221 Win=50400 Len=21    "MSG_3 ECHO"
 35 2.087196    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=169 Ack=221 Win=50400 Len=21    "MSG_4 ECHO"
 36 2.087500    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=190 Ack=221 Win=50400 Len=21    "MSG_5 ECHO"
 37 2.165390    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=148 Win=66632 Len=0
 38 2.166314    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=190 Win=66588 Len=0
 39 2.364135    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=211 Win=66568 Len=0

レッドハット

 17 2.081163    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=111 Ack=106 Win=66672 Len=22    "MSG_1 RCV"
 18 2.081178    server         client          TCP      6006 > 55879 [ACK] Seq=106 Ack=133 Win=5888 Len=0
 19 2.081297    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=106 Ack=133 Win=5888 Len=21 "MSG_1 ECHO"
 20 2.081711    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=133 Ack=106 Win=66672 Len=22    "MSG_2 RCV"
 21 2.081761    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=155 Ack=106 Win=66672 Len=22    "MSG_3 RCV"
 22 2.081846    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=127 Ack=177 Win=5888 Len=21 "MSG_2 ECHO"
 23 2.081995    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=148 Ack=177 Win=5888 Len=21 "MSG_3 ECHO"
 24 2.082011    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=177 Ack=106 Win=66672 Len=22    "MSG_4 RCV"
 25 2.082362    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=199 Ack=106 Win=66672 Len=22    "MSG_5 RCV"
 26 2.082377    server         client          TCP      6006 > 55879 [ACK] Seq=169 Ack=221 Win=5888 Len=0
 27 2.171003    client         server          TCP      55879 > 6006 [ACK] Seq=221 Ack=148 Win=66632 Len=0
 28 2.171019    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=169 Ack=221 Win=5888 Len=42 "MSG_4 ECHO + MSG_5 ECHO"
 29 2.257498    client         server          TCP      55879 > 6006 [ACK] Seq=221 Ack=211 Win=66568 Len=0

そのため、RH で正常に動作していないことを確認しました。パケット 28 の送信が遅すぎます。サーバーは、何かを行う前にパケット 27 の ACK を待っているようです。

私にはそれが最も可能性の高い理由のようです...

次に、Solaris と RH のダンプで「Win」パラメータが異なることに気付きました。Solaris では 50400、RH では 5888 のみです。それは別のヒントです...

スライド ウィンドウとバッファ ウィンドウに関するドキュメントを読み、ソケットの Java で rcvBuffer と sendBuffer をいじりましたが、この 5888 値を他の値に変更することはできませんでした (毎回 tcpdump で直接確認しました)。

誰もこれを行う方法を知っていますか? 場合によってはバイパスする必要があるかもしれない「自動ネゴシエーション」などがあるため、決定的な情報を得るのに苦労しています...

最終的に、RH で「tcp_slow_start_after_idle」パラメーターを 0 に設定することで、最初の問題を部分的にしか取り除くことができませんでしたが、「win」パラメーターはまったく変更されませんでした。5 つのメッセージの最初の 4 つのグループに同じ問題があり、tcpdump で TCP 再送信と TCP Dup ACK が発生し、その後の 5 つのメッセージのすべてのグループで問題が完全に解消されました。

私にとっては、非常にクリーンで一般的なソリューションのようには思えません。両方の OS でまったく同じ条件を再現したいと思っています。

私は調査を続けますが、TCP の専門家からの助けをいただければ幸いです。

4

1 に答える 1

1

輻輳回避アルゴリズムが Red Hat ボックスに適用されているようです。

パケット 26 の時点で、サーバーはクライアントからのすべてを確認して ACK を送信しましたが、クライアントはサーバーの最初の SYN に対してのみ ACK を送信したことに注意してください。サーバーのメッセージにはまだACKを送信していません。また、パケット 27 は、サーバーの最初の 2 つのデータ ロット (パケット 19 と 22) を確認するクライアントです。

Red Hat ボックスが使用している輻輳制御アルゴリズムはどれですか? ( /proc/sys/net/ipv4/tcp_congestion_control) - 他の使用可能なものに切り替えてみてください。

于 2010-06-08T12:51:39.547 に答える