追記
いくつか誤植を修正しました。
- Cluster API へのリンク
- Ruby のようなフルスタックにうんざりしているんだ => Rails のような~
Node 関連で良く聞かれる質問を集めて見ました。
この記事を通して Node について持っていた疑問を解消し、Node の良いところも、「ちょっとなぁ。。」なところも合わせて、きちんと理解する助けになればと思います。
そもそも "Node" なの? "Node.js" じゃないの?
当初は "Node.js" と呼ばれていましたが、「正式名称は "Node" である。ただし曖昧さが出る場合は "Node.js" と表記しても良い」という旨の記述が本家の Wiki にあります。
What is the correct capitalization of Node.js?
日本のコミュニティもこれに合わせて Node と記述するようにしている人も多いです。
確か "Node.js" って書くとクライアントサイドの JS ライブラリ(etc prototype.js)みたいに勘違いされる可能性がある、みたいな理由だった気がしますが、
自分は正直 Node って言葉が汎用的すぎるので、まあこだわりすぎなくても良いかなと思うのが本音です。コンテキストで両方使い分けています。
どんな人たちがいるの?
Ruby => Rubyist, Python => Pythonista, という流れでいえば、Node の技術者は Noder という通称になります。
海外の Noder の多くは、Ruby から来た人が多いという話を聞きました。
Github を中心としたエコシステムだったり、Rails Ramdle を模した Node KnockOut といったイベントがあるのもその影響でしょうか。
Haml, Sass, Sinatra といった Ruby 発祥のライブラリ(やそのアイデア)もどんどん Node に移植されています。その点で Ruby の文化を継承している印象があります。
作者の Ryan Dahl も元は Ruby のサーバを書いたりしていました。
日本では、まだコミュニティは大きいとは言えませんが、色々なバックグラウンドの人が集まっています。
面白いのは、「クライアントサイド JS をバリバリやってきました!」という人ばかりではないという点ですね、
Ruby, Java, Python, Perl, Flash, C++ etc
色々な人が集まっているので、刺激があって面白いと思います。
企業も注目してるの?
まず、作者の Ryan や npm の作者 isaac は Joyent というクラウドホスティングサービスの企業に在籍しています。
Joyent は Node のビジネスユースを拡大するために色々とプランを練って動いているようです。
Heroku や DotCloud から Microsoft と言った様々な企業も、特にクラウド関連のプラットフォームについて、 Node に興味を示していることもニュースにあがるようになりました。日本では、主要なソーシャルアプリやゲーム系の会社のあいだで、ちょっとづつ「無視はできない」感じになってきているという話も聞きます。
そして日本でも FirstServer さんが、 Node のホスティングサービスをはじめるそうです。今後の展開に期待したい所です。
ES5, harmonyは?
Node は JS の処理系に Google v8 を使っています。
v8 は ES5(Ecma Script 5) のほとんどを実装しているため、その機能であれば Node から自由に使うことができます。
v8 で使える ES5 の機能は以下にまとまっています。
ECMA-5-Mozilla-Features-Implemented-in-V8
(拙作ですが参考 Node で使える ECMA Script 5 の新機能 にてこの内容を紹介しています。)
また、Node の v0.5.4 頃からは --harmony オプションつけると harmony_proxies と harmony_weakmaps などの機能が使えるようになっています。
サーバでの使用は、クライアントのようにブラウザ間の互換性を気にせずに、安心して使える(Node 自体のバージョンの互換は別)ので、
JavaScript 好きにはとても嬉しいことではないでしょうか?
Web サーバなんだっけ?
Web アプリケーションサーバではありません。
Apache, Nginx のような HTTP サーバ実装でもなければ、Tomcat のようなアプリケーションサーバでもありません。
Node はあくまでサーバサイドで JavaScript を動かす実行環境です。
そして、標準のモジュールだけで HTTP サーバ、 TCP サーバ、ファイルサーバなどが、簡単に実装できるようになっています。
簡単と言ってもヘッダを自分でいじるなど、それなりの知識を要するかもしれませんが、同じ事を C などでやるのと比べれば、
よっぽど手軽かと思います。
そしてそれを使って Apache などのように .html/.css/.js/.png を配布する Web サーバを実装することもできれば、Web アプリケーションを実装することもできます。
パーサを書けば WebSocket を読むこともできて、こうしたところが Node で Ryan が目指した「手軽にネットワークプログラミングをする環境」を表していると思います。
Node で作った Web アプリは何にデプロイするの? Apach mod_nodejs は?
上の質問ともからみますが、Node は http という標準モジュールを持ち、これを用いると非常に簡単に HTTP サーバを作ることができます。
そして多くの Web アプリ用フレームワークは、このモジュールで HTTP リクエストとレスポンスを操作し、アプリを成立します。
つまり、 Node で作った Web アプリは、何か別の HTTP サーバ(Apach, Unicorn, Mongorel etc)にデプロイすること無く、Node プロセスを起動するだけで稼働することができます。
サーバ書いたんだけどどう運用するの?デーモン化は?
サーバを書いたら node コマンドで起動できるのは良いのですが、そのまま運用となるとちょっと心もとないです。
Node もすでにプロダクション環境で動いている例もあるため、プロセスを管理するためのノウハウやツールもいくつかあります。
多いのは node 製のプロセス管理ツールである forever を用いる方法や、 deamontools で管理する方法です。
他にも最近は Joyent や Heroku, DotCloud など、Node に対応した PaaS が多くありますので、それらを利用するのも良いと思います。
シングルプロセスなんでしょ?マルチコアは使えなくない?
Node は単一のプロセスで、複数のI/Oを非同期に効率よくさばくことに長けた設計になっています。
なので node コマンドで単純に起動したらプロセスが一つ立ち上がります。
単一のプロセスでもある程度の性能は出ますが、それでも足りない場合は複数プロセスの起動が必要になるでしょう。
アプローチは大きく二つあります。
- 複数のプロセスを並列に起動しロードバランスする
- 特定の処理専用のワーカプロセスを起動し、マスタプロセスから処理を委譲する
方法はいくつかがあって、ツールとして Cluster や node-webworker 、標準でも child_process などが利用できますし、
前述の Heroku なども複数プロセスの起動に対応しています。
また、 Node v0.5.10 からは、複数プロセス起動の cluster オプション がサポートされました。
このオプションは、単純にプロセスを同時起動するだけなので、複数起動したプロセス間のデータ共有などは、外部に Redis などの共有ストレージを立てるといったことが別途必要になりますが、非常に重要なオプションとなることでしょう。
フィボナッチ遅いんでしょ?
Node の仕組み上、 I/O ヘビーな処理をさばくことに長けていますが、CPU ヘビーな処理(例えばフィボナッチのように CPU 計算を沢山する処理)には長けていません。
Node はイベントループという仕組みを用いて、I/O 中には別の処理を行うことで、単一のスレッドでも多くの処理を同時にさばくことができるようにしました。
「シングルスレッド+非同期処理」なモデルです。これはスレッドの数が少ないという点で、メモリの節約にもなります。
こうした I/O ヘビーな処理を効率よくさばくことができる点が、 Node が「リアルタイム Web アプリ」と相性が良いと言われる所以の一つです。
WebSocket じゃなくて Ajax でも構いません。ネットワーク経由でのファイルのアップロードなんかも向いてるでしょう。
「大量のクライアント(PC, スマホ, タブレット, Bot, etc) から、大量の HTTPリクエスト(ネットワーク I/O) が来て、
レスポンス(これもネットワーク I/O)には MySQL からデータを取らないといけない(ディスク I/O)」
こんな場面こそ Node はその真価を発揮します。
逆に CPU ヘビーな処理は Node には向いているとは言えません。良く Ryan 本人が 「ビデオエンコードとか、 3D の演算なんかをするためじゃない」といった例を出すのは、Node はそうした「大量の計算を必要とする処理」を対象としていないというだけの話と考えます。
もし CPU ヘビーな処理をしたい場合には、それ専用の子プロセスを fork して、そちらで実行し結果を受け取ると言った方法や、
C 、C++ でアドオンを書くといった方法があります。
「フィボナッチを速く出したいだけなら、他の言語でやったらいいのでは?」ということかと思います。
環境を作るの大変? Windows は?
多くの言語で使用されている環境管理とパッケージ管理が Node でも用意されています。
環境管理
- Ruby の rvm
- Python の virtualenv
- Perl の Perlbrew
- Node では nvm か nave
パッケージ管理
- Ruby の gem
- Python の PyPi
- Perl の CPAN
- Node では npm
環境管理は nvm と nave の二つがあり、一長一短がある感じです。自分は nvm を使ってますが zsh と相性が悪いなどがあり、初めて使う場合は nave を入れておくのが吉かもしれません。もちろんソースからビルドすることもできます。Windows の場合は最近 node.exe の配布が始まったので、それをパスの通ったディレクトリに置くだけで実行が可能です。しかし npm はもともと sh で書かれているため、 Windows ではそのまま動かせないため、現在 windows 対応が進められています。
ライブラリって結構あるの?
いわゆる標準以外のライブラリは、Node ではモジュールと呼ばれていますが、モジュールはかなり広い範囲がカバーされています。
本家リポジトリの Wiki にもそれをまとめたページがあります。https://github.com/joyent/node/wiki/modules
見れば一通り揃っていることがわかるでしょう。
しかし、逆に我先にとみんなが作り出し乱立したモジュール(例えば MySQL クライアントとか)や、作ったは良いけど全くメンテナンスされてないものも多く有るので、
ここにある全てが未だに現役かというとそうとも言えません。動かないものも有るでしょう。(そもそも Wiki なのでここに書かれたのはあくまで自己申告です。)
導入する際には、コミットの履歴や Fork/Watch/issue/pull request の数などを確認し、そのモジュールが活発に開発されているかなどもチェックすると良いでしょう。
(またまた拙作ですが、それをチェックするための [Bookmarklet(http://d.hatena.ne.jp/Jxck/20110924/1316850060) を書いてたりします。ご参考まで。
相性の良い DB
Node と合わせてよく使用される DB には MongoDB や Redis といった NoSQL が多いかと思います。
まず Node が JavaScript を用いて実装するため JSON (やそれに近い形式) でデータを格納する MongoDB や CouchDB といった、
ドキュメント指向の DB と非常に相性がいいことがあげられます。特に MongoDB とは 「鼻血が出るほど相性がいい」と発表されていた例もあります。
次に速度です。Node はリアルタイムアプリケーションと言った高速な応答が求められる場面で使われることも多いため、ストレージにも速度を求める場合が有ります。
こうした時に memcache や redis が用いられることが多く、特に redis は良く組み合わせられる印象が有ります。
もちろん MySQL や PostgreSQL といった定番の RDB 用のクライアントもあり、 ORM も開発されています。
Web Application Framework はどんな感じ?
Node で最も人気のある Web Application Framework は、現状 Express かと思います。
Express は Ruby の Sinatra にインスパイアされており、軽量な設計になっています。一方 Rails のようなフルスタックな FW として Geddy というものもあります。
なぜ Geddy のようなフルスタックなフレームワークではなく、軽量な設計の Express の方が好まれるのかというと、プロジェクトの活発度や使いやすさなど様々な要因があと思いますが、「Node に流れて来た Ruby(on Rails)開発者は、Rails のようなフルスタックにうんざりしているんだ」
という話を聞いたことがあります。
それ以外にも、 MVC でいう V(view) 層の多様化など色々な要因が有るとは思いますが、事実 Node では、全てを網羅したフルスタックなものよりも、単機能に絞ったモジュールを公開し、それを自分で選択して組み合わせるという流れが多いように思います。パッケージマネージャの npm も細かく依存をコントロールする機能を備えてそれを後押ししています。
Socket.IO っていう WebSocket のライブラリがあるんでしょ?
実用上ほとんど正しいんですが、正確に言うと少し違います。
なぜなら Socket.IO がカバーしているのは WebSocket だけではないという点です。
WebSocket は現状未実装だったり、実装されていてもデフォルトで無効になっているブラウザが多く、必ず使えるとは限りません。
しかし、 Socket.IO は WebSocket 以前に行われていたサーバからの Push 技術を併用し、
「WebSocket が使えないブラウザは、別の通信方法にフォールバックする」という仕組みを取り入れる事で、
この問題を解決しています。
現在 Socket.IO がフォールバックに使っている技術は以下の用なものがあります。
- Adobe® Flash® Socket
- AJAX long polling
- AJAX multipart streaming
- Forever Iframe
- JSONP Polling
Forever Iframe や JSONP Polling あたりを使えばかなり広い範囲のブラウザまでサポートできます。
(もちろんパフォーマンスは悪くなりますが) 現在ドキュメントにあるサーポートブラウザは以下です。
Desktop
- Internet Explorer 5.5+
- Safari 3+
- Google Chrome 4+
- Firefox 3+
- Opera 10.61+
Mobile
- iPhone Safari
- iPad Safari
- iPad Safari
- Android WebKit
- WebOs WebKit
ということで、 「WebSocket の」よりは「WebSocket も」になります。
自分は一応「リアルタイム通信モジュール」といった紹介の仕方をしています。
また純粋に 「WebSocket のライブラリ」というのであれば、
Socket.IO も内部で使用している node-websocket というライブラリがそれにあたります。
おわりに
良く聞かれる質問についてはだいたい書かせていただきました。
これらを通じて Node について、「良い面」「悪い面」も含めて正しく理解していただければと思います。
こうしている間にも Node やそれを取り巻く環境は進歩し、今も次のメジャーバージョン v0.6 リリースに向けた作業が進んでいます。
ここに書いていることも、少しずつ変わっていくかもしれません。
また、他にも質問があったら、コメントに書いていただければ、余力がある範囲で追記します。
Jxck