node.jsの仕組み(ノンブロッキングI/Oとかスレッドとか)

サーバーサイドjavascriptで一世を風靡しているnode.jsですが、PHPで書くサーバーサイドのプログラムと何が違って何がいいのか。

「なんかいい」とかじゃ使えないしってことで調べてたら知らないことがたくさん出てきたんでメモ。

 

簡単に言うと、node.jsが今までと違うのは

「イベントループモデルで、ノンブロッキングI/Oを使用している」

点らしい。

はてな。

 

イベントループモデルとスレッドモデル

スレッドモデルとイベントループモデルは、ざっくりいうと「スレッドでの処理の仕方」を大まかに2つに分けたもの。

そもそもスレッドというものは「処理の流れ」を意味している。

 

後の説明もあるので若干分かりにくいたとえだけど、「店頭でゲームソフトを購入する」処理に例える。

分かりやすく処理の流れを店員の視点で

1.レジに空箱が持ちこまれる

2.棚まで本体を取りに行き、本体を棚から探す

3.本体を客まで持っていって会計をする

の3つ程度に分ける。

 

スレッドというのはこの一連の処理のことをいう。

一般的なWeb上のやり取りで言えば、

1.クライアント側(ブラウザなど)からフォームを送信する

2.サーバー側でデータをデータベースに挿入したり、必要なデータを取り出す

3.取り出したデータを計算したり、加工するなどして表示する

でいいと思う。

さて、そこに2人目の客が商品を持ち込んだ。

この2つのモデルの違いは、ここで店員1人が客2人分の処理を行うのがイベントループモデル

もう1人店員が出てきて会計をするのがスレッドモデルである。

 

スレッドモデルとは複数のアクセスがあったときに、スレッドを複製して処理を行うことを意味する。

スレッドが複製されればされた分、CPUを食う。

店員の例でいうとアクセスが増えるほど店員が増えていき、増やせば増やすだけ人件費(処理時の負荷)がかかる。

 

一方のイベントループモデルはアクセスが複数あっても、スレッドの数は増えない。

CPUの面でいうとスレッドモデルよりも、有利である。

店員の例でいえば、1人の店員ですべてを処理して人件費を削減しているイメージ。

 

 

しかし、2.の処理であるゲームソフト本体を棚から探し出してくる作業が実は厄介になってくる。

これがI/O(Input/Output)で、主にデータベースやネットワークなどからデータを出し入れしたりする作業を指す。

http://d.hatena.ne.jp/badatmath/20101020/1287587240

この記事によれば、これらI/Oに対する時間の掛かり方が、他の処理に比べるととんでもないらしい。

例えを用いるなら

I/O処理=希望のゲームソフトを棚から探して取り出す作業

他の処理(主にCPU上の処理)=会計など

 

この出し入れの作業にかかる時間が他の処理の1万倍多くかかるとしたら、1人の店員が全ての仕事をするスタイル(イベントループモデル)ではとても営業できない。これまであったイベントループモデルの技術は極端だがこういうイメージ。ちょっと扱いが難しい。

そういう訳でスレッドモデルが採用されているApachePHPやらなんやら)が主流でなじみ深いものになってたのかな。

 

ブロッキングI/OとノンブロッキングI/O

出し入れ作業(I/O)は時間がかかる。

このとても時間のかかるI/Oの処理で、商品が見つかるまでじっと棚の前で待っているのがブロッキングI/Oと呼ばれるモデルである。

処理が文字通りブロックされているイメージでいい。

んで、商品が見つかるまで棚の前で待たずに次のお客さんの対応に回ることができる。これがノンブロッキングI/O。他の処理を行いながら、商品が見つかり次第棚から持っていき会計する処理に取り掛かる。

出し入れ処理がブロックされない。

 

node.jsはイベントループモデルかつノンブロッキングI/Oと最初に言った。

 

node.js→レジと棚の間を1人の店員が立ち止まることなく、1~3の処理を効率よく行う。

Apache→たくさん店員が出てくるが、棚の前で商品が見つかるまでじっと待つ。

 

 

こんな感じの理解でいいですかね。

何かあればご指摘ください。