Anarchy In the 1K

スケーラブルI/O実現方法の調査

背景

 スケーラブルなI/Oに関して、以下書籍で勉強しています。


スケーラブルなI/Oの実現方法に関して、こちらでは以下の通り記載があります*1

I/Oのノンブロッキングモードと多重化によって、同時接続数が数千にも達する大規模なWebサーバとアプリケーションサーバの開発が可能になり、複数のプロセッサを有効利用できるようになります。...個々の接続に専用のスレッドを割り当てる必要がないからです。

 ノンブロッキング多重化がキーワードになる様です。これらに関して、調査した結果を以下にまとめます。

ノンブロッキングとは

 ノンブロッキングに関して、カーネルがI/O処理の準備中*2だった際に、アプリケーションが準備完了を待たないことを表します。 合わせて、こちらの記事もご覧ください。

I/Oの多重化とは

 1つのスレッドで、複数の接続を管理する仕組みのこと。具体的には、状態*3が変更された接続をスレッドに通知することで実現する。つまり、イベント駆動での処理が可能になります。

疑問点

 I/Oの多重化を用いれば、I/O処理の準備完了が通知される為、準備完了を待たないノンブロッキングI/Oでなく、準備完了を待つブロッキングI/Oで良いのではと疑問に思いました。
 上記に関して調べたところ、ある接続を複数のスレッドが利用する場合、以下の様に状態が変更される可能性がある様です。

  1. スレッド1が、ある接続のI/O処理の準備完了を通知される。
  2. スレッド2が、上記接続を利用したI/O処理を行う。
  3. スレッド1が、I/O処理を試みたところ、I/O処理の準備中であり、待ちが発生する。

 その為、書籍ではスケーラブルI/Oとして、I/Oの多重化とノンブロッキングI/Oが紹介されています。

まとめ

 ブロッキングI/Oを用いると、I/O処理の準備完了の待ちが発生する為、1つのスレッドが1つの接続の管理に掛かりきりになります。
 I/Oの多重化とノンブロッキングI/Oを用いれば、I/O準備完了の通知を受け、仮に実行前にその状態が変わっても待ちが発生しない為、1つのスレッドで複数の接続の管理が可能になります。
 結果として、よりスケーラブルなI/Oが実現できるということですね。

*1:該当箇所はp.75

*2:ソケット送信バッファに空きがない場合や、ソケット受信バッファにデータがない場合

*3:I/O処理の準備完了や、タイムアウトの発生など