メインコンテンツへスキップ
「このアプリケーションは何年も問題なく動作していました。先週ネットワークがアップグレードされ、100Mbpsからギガビットに移行しました。すると一部のメッセージの後半部分のデータが文字化けするようになりました。ネットワーク担当者はネットワークの問題ではないと断言していますが、変更されたのはネットワークだけなのです。」

 

良い知らせは、高額なネットワークのアップグレードがアプリケーションを壊さなかったことです。

 

悪い知らせは、アプリケーションが壊れており、常に壊れていたということです。TCPアプリケーションを書く*多くの*人々が気づいていないのは、TCPがメッセージではなくバイトのストリームであるという事実です。アプリケーションが2つの1000バイトメッセージを送信しても、送信側のTCPスタックが2つの1000バイトTCPセグメントを送信するとは限りません。 アプリケーションメッセージは、受信側が宣言した最大セグメントサイズ(MSS)や送信側の設定制限に基づき、より小さな断片に分割される可能性があります。再送処理もアプリケーションメッセージを結合・断片化します。たとえ送信側TCPスタックが実際に2つの1000バイトTCPセグメントを送信しても、受信側TCPスタックがアプリケーションに2つの1000バイトメッセージを確実に渡す保証はありません。 例えば、アプリケーションのバッファが500バイトしかない場合、TCPスタックが返すのはその分だけである。一方、バッファが1500バイトで1000バイトセグメントが両方到着している場合、TCPスタックは最初の呼び出しで1500バイトを返し、2回目の呼び出しで500バイトを返す。バイトストリームを受け取り、それを正しくメッセージに再構成するのはアプリケーションの責任である。

 

これはネットワークのアップグレードとどう関係するのでしょうか? OpenVOSサーバーとLinux 異なるサブネット上に存在したため、OpenVOSシステムは最大セグメントサイズを536バイトと広告していました。 クライアントから送信されるアプリケーションメッセージは1000バイトであったため、メッセージは2つのセグメントに分割されていました。アップグレード前は、アプリケーションが受信処理を開始する前に両方のセグメントがOpenVOSサーバーに到着していたため、1回の受信関数呼び出しで1000バイト全てが読み取られていました。しかしアップグレード後、セグメントの到着タイミングが変化したため、アプリケーションが受信処理を開始した時点で最初のセグメントしか利用できない場合が生じるようになりました。 アプリケーションバッファの最後の464バイト(1000バイト - 536バイト)はTCPスタックによって埋められず、受信要求発行前に存在した任意のガベージデータが保持された。

 

このケースでは簡単な応急処置がありました。OpenVOSの広告MSS値を1460に増やすことです(サブネット間でのTCPスループットを改善する簡単な方法参照)。しかしこれはあくまで一時的な対策に過ぎません。真の解決策は、1回の受信呼び出しで1つのメッセージが返されると仮定するのではなく、コードを書き直してTCPバイトストリームをアプリケーションメッセージに正しく解析し直すことです。

© 2024 ストラタス・テクノロジーズ