web-dev-qa-db-ja.com

クライアント側で十分なウィンドウが利用できるのに、TCPサーバーがACKを待機するのはなぜですか

2つの異なるRed Hatマシンで実行されるサーバーアプリケーションとクライアント間のTCP接続で以下の動作を観察しています。

例1

  1. クライアントはこれまですべてを確認します(WND = 1424のACK)
  2. サーバーは296バイトをTCPレイヤーに送信し、クライアントに送信します(プッシュ/ ACK)
  3. サーバーは296バイトをTCP=レイヤーに送信し、クライアントに送信されます(プッシュ/ ACK)
  4. サーバーは296バイトをTCPレイヤーに送信し、クライアントに送信します(プッシュ/ ACK)
  5. サーバーは239バイトをTCPレイヤーに送信/送信しようとしますが、次の2つのいずれかが発生します
    1. oSは、これらのバイトを送信する前に、クライアントからのACKが受信されるまで約30ミリ秒待機します(このxバイトの送信は、以下で遅延メッセージと呼ばれます)。
    2. tcp send呼び出しはEWOULDBLOUCKまたはEAGAINを返します(239 + 239 + 239 + 239 <1424であるため、これは不可能だと思います。間違っている場合は修正してください

例2

  1. クライアントはこれまですべてを確認します(WND = 1424のACK)
  2. サーバーは239バイトをTCPレイヤーに送信し、クライアントに送信します
  3. サーバーは239バイトをTCPレイヤーに送信/送信しようとしますが、上記の2つのいずれかが発生します

私が理解したい問題は、クライアントのウィンドウサイズが十分に大きいときに、サーバーアプリケーションまたはOSがACKまで待機する理由です。これは私がOSレベルで調整できるものですか。クライアントのウィンドウがいっぱいになるまでサーバーにすべてのバイトを送信させることができますか?

私の理解によると、2つの考えられる理由があります

  1. サーバーアプリケーションは、送信システムコールがEWOULDBLOUCKまたはEAGAINを返したため、「遅延メッセージ」をTCPレベルに渡しません。
  2. アプリケーションはメッセージをTCPレイヤーに渡しますが、オペレーティングシステムは、クライアントからのACKを受信するまでメッセージを送信しません。

すべての遅延メッセージのシナリオでは、遅延メッセージの送信前にクライアントからのACKがあります。また、アプリケーションの動作ロジックは、メッセージをTCPレイヤーに渡すことを示唆しています。

これのトラブルシューティングに焦点を当てるべき場所を提案していただけますか。

  1. クライアント側またはサーバー側で設定できるOSレベルの設定ですか?
  2. これはどういうわけかアプリケーションサーバーの障害ですか?
  3. メッセージがウィンドウを埋めるまでOSがEWOULDBLOCKを返さないと仮定するのは間違っていますか?

編集:複製の理由:問題がどこにあるのかわかりませんでした。 network/os。追加の詳細を追加しました。また、TCP Linuxの実装からのPOVが必要なので、この質問はここにあると思います。

3
PasanW

これは「遅延ACK」と呼ばれ、TCPプロトコルが機能します。詳細については https://en.m.wikipedia.org/wiki/TCP_delayed_acknowledgment を参照してください。 。アプリケーションのパフォーマンスに影響する場合は、この機能を無効にできます。iSCSIがACKの遅延をデフォルトでオフにしているとします。

3
RiGiD5