くたくたシェルのブログ

気ままに楽しむ燃え殻 (ash) のような人間が自分の頭の舵取りをするために書いています。つぶやくよりは考え、考え過ぎるよりは吐き出す、そんな記録を脳みその外に置きます。

Node.jsの第三歩:ノンブロッキングI/O事始め

前の日記: Node.jsの第二歩:便利そうなモジュールを追加インストール - くたくたシェルのブログ で参考にした記事で、「シングルスレッドでノンブロッキングI/Oなのはマルチスレッドとは違う」という旨が書かれていたが、非同期処理とどう違うのかなと違和感を覚えていた。そうしたら、後日解説記事があった:

www.atmarkit.co.jp

要するに、非同期処理のことらしい。

イベントループを回している処理を担うスレッドが1つというだけで、全体としては並行処理しているわけだから、「シングルスレッド」にこだわる必要はなさそう。モデルの上では、並行処理が可能であればよいわけで、実体はマルチスレッドあるいはマルチプロセスでもいいわけだ。バックグラウンドジョブとしてプロセスを起動して、ループを回して処理を担う、たとえばスケジューラのようなスクリプトと処理形態は似ている。

なお、解説の中で、

そのため、ログの順番は、「start」「end」「response end」の順になります。

とあるのだが、おそらく必ずしもそうはならないのではないか?startは最初だとしても、endとresponse endの順序は保証されない、ということなのだと思う。

注意点は2つあるとのことで、

  1. コールバック関数の中でレスポンスの返し忘れがあると、処理をブロックしてしまう。(ここでいうブロックとは待ち状態になること?)また、別のクライアントからの要求が来ても並行して延々と待ち続けてしまい、イベントキュー?相当のリソースを食いつぶしてしまう。ただし、タイムアウトによりリソースが解放されるなら話は別だが、度を越すと 503 Service Unavailableなどになるリスクが残ることに変わりはない。
  2. レスポンスを返す役割を担うコールバック関数よりも先にレスポンスを返してしまうと、期待するレスポンスが返されない。

重たい処理はバックグラウンド処理(コールバック関数)にやらせておいて結果を後で取り出す必要が生じる。その仕組みとしては WebSocket, Commet, Ajax があるとのこと。

  • Commet(コメット)はレスポンスをすぐに返さずにリクエストを保持しておき、イベントが起きてから返すことらしいのだけど、これって要するに普通のHTTP リクエスト&レスポンスとどう違うのかな?そもそもあまり聞かない用語。プッシュ型?タイムアウト相当の概念がないと大量同時接続時にリソースがパンクするのが目に見えている怖いアプローチじゃないかと思われます。
  • Ajax を使う方法は要するにpollingするということなので、あまりやりたくない。せめて回数制限(タイムアウトに相当)をつけておかないと実際の運用で困りそう。(サーバー、ネットワークのリソース・負荷の面で)

そういうわけで、Node.jsでノンブロッキングなコールバック関数とイベントハンドラを慎重に書いたあとは、WebSocketですかね。