SocketChannel.write()を使用して大量のデータを送信しているときに、基礎となるTCPバッファがいっぱいになって、write()を続けて再試行する必要があります。データはすべて送信されます。Java NIO SocketChannel.write()でのスレッドの問題
だから、私はこのようなものを持っているかもしれません:
public void send(ByteBuffer bb, SocketChannel sc){
sc.write(bb);
while (bb.remaining()>0){
Thread.sleep(10);
sc.write(bb);
}
}
問題は大のByteBufferと溢れ根本的なTCPバッファと時折問題は、この呼び出しが予期しないためにブロックされます)(送信することを意味していることです時間の長さ。私のプロジェクトでは、同時に数百のクライアントが接続されています.1つのソケット接続に起因する1つの遅延は、1つのSocketChannelでこの1つの遅延が解決されるまでシステム全体をクロールさせます。遅延が発生すると、プロジェクトの他の領域での速度低下の連鎖反応が発生し、レイテンシが低いことが重要になります。
このTCPバッファオーバーフローの問題を透過的に処理し、SocketChannel.write()への複数の呼び出しが必要なときにすべてをブロックすることなく解決するソリューションが必要です。私はsend()をスレッドを拡張する別のクラスに入れることを考えました。それは独自のスレッドとして実行され、呼び出しコードをブロックしません。しかし、SocketChannel.write()が最初の試行で成功した場合、特に99%の時間がかかると、スレッドがそこに存在する必要はありません。 。 (つまり、send()を別のスレッドに入れることは、while()ループが使用されている場合にのみ必要です。バッファの問題がある場合(たぶん1%の時間)バッファの問題がある場合時間のわずか1%で、私はsend()の呼び出しの他の99%に対してスレッドのオーバーヘッドを必要としません。
私はそれが理にかなってほしいと思っています...私は本当にいくつかの提案を使用することができます。ありがとう!
ソケットが完全なバッファでブロックされていない場合、元のポスターは言っていません。 –
バッファは、クリアするために常に少なくとも10ミリ秒かかると仮定します。個人的には、バッファがほとんどすぐにクリアされない場合、バッファが小さすぎるか、リーダーが遅すぎるかのいずれかです。私は接続を閉じます。 –
例のバイトバッファがカーネルのソケット出力バッファより大きい場合、コードはネットワークアダプタが書き込むことができ、したがってオーバーランしてスリープするよりも速く書ける可能性があるため、非効率的です。 10msスリープ状態では、ネットワークアダプタは1Gbネットワークに約1MBを書き込むことができます。通常のソケット出力バッファサイズよりも大きくなります。バイトバッファがほんの数KBであれば、読者が遅すぎるかもしれませんし、OP_WRITEを使用すると少し複雑になりますが、バッファアンダーランだけでなくスレッドをスリープ状態にするのを避けることができます。 –