Node.js とは一体何か?

すぐにコーディングを開始できるサーバー

Node.js はサーバー・サイドの JavaScript インタープリターであり、サーバーの動作に関する概念を変えるものです。Node.js が目指しているのは、プログラマーが非常にスケーラビリティーの高いアプリケーションを構築できるようにすること、そして何万もの同時接続をたった 1 台の物理マシンで処理できるコードを作成できるようにすることです。

Michael Abernethy, Programmer, Freelancer

Mike AbernethyMichael Abernethy は多種多様な技術を扱い、また広範にわたる顧客と共に作業を行ってきました。彼が取り組んでいるのは、より優れていて複雑な Web アプリケーションを作成すること、それらのアプリケーションを実行するブラウザーの限界をテストすること、そしてそのアプリケーションの作成および保守をもっと容易に行えるようにする方法を見つけることです。コンピューターで作業をしていないときは、子供と本を読んだりして過ごしています。



2011年 6月 09日 (初版 2011年 6月 03日)

はじめに

Node.js について聞いたことがある人や、Node.js がいかに素晴らしいかを解説した記事を読んだことがある人であれば、「Node.js とは一体何なのだろう?」と思っているかもしれません。さらには、そうした記事を掲載しているホームページを読んだ後ですら、Node.js とは何であるかについて疑問を持っているかもしれません。Node.js は必ずしもすべてのプログラマーに必要なものではありませんが、一部の人にとっては適切な選択肢となる可能性があります。

この記事では、「Node.js とは何か?」という疑問に答えるために、Node.js によって解決できる問題や Node.js の動作、Node.js を使った単純なアプリケーションを実行する方法、そしてどのような場合に Node.js がソリューションとして適しているのかについて、簡単な基礎知識を提供します。しかし、この記事では複雑な Node.js アプリケーションの作成方法について説明するわけでも、Node.js に関する詳細なチュートリアルを提供するわけでもありません。この記事の目標は、皆さんが自らのビジネスで利用するために、Node.js をさらに詳しく学ぶ必要があるかどうかを判断できるようにすることです。


Node.js ではどんな問題を解決できるのか

Node.js の第 1 の目標は、「スケーラブルなネットワーク・プログラムを作成するための簡単な方法を提供すること」とされています。現在のサーバー・プログラムでは何が問題なのでしょう?まず計算をしてみましょう。Java や PHP のような言語では、接続ごとに新しいスレッドが生成されますが、1 つのスレッドには潜在的に 2 MB のメモリーが必要となります。つまり 8 GB の RAM を持つシステムにとっては、同時接続可能な最大ユーザー数は理論的には約 4000 ユーザーということになります。顧客ベースが拡大した場合、Web アプリケーションがもっと多くのユーザーをサポートするようにしたいのであれば、さらに多くのサーバーを追加する必要があります。もちろん、それによってビジネスに伴うサーバー・コスト、トラフィック・コスト、および作業コストなどが増加します。こうしたコストの問題に加え、技術的な問題も潜在しています。それは、1 人のユーザーがリクエストごとに異なるサーバーを使用する可能性があるため、すべての共有リソースはすべてのサーバー間で共有しなければならないということです。こうしたすべての理由から、(トラフィックのスループットや、プロセッサーの速度、そしてメモリーの速度を含む) Web アプリケーション・アーキテクチャー全体でのボトルネックとなるのは、サーバーで処理可能な最大同時接続数です。

Node.js はサーバーへの接続方法を変更することにより、この問題を解決します。接続ごとに新しい OS スレッドを生成する (そして、それに付随するメモリーを割り当てる) のではなく、それぞれの接続が Node.js エンジンのプロセス内で実行されるイベントを起動するのです。また、Node.js は決してデッドロックは発生しないことを謳っていますが、それは Node.js ではロックが許可されないので、I/O 呼び出しを直接ブロックすることがないからです。さらに、Node.js を実行するサーバーは何万もの同時接続を処理することができるとも謳っています。

では、何万もの同時接続を処理することができるプログラムを実現できるのであれば、Node.js を使用すると実際のところ何を構築できるのでしょうか?そうした多くの接続を必要とする Web アプリケーションにとって、Node.js は最高の選択肢となるでしょう。これは「問題があると言っても、それは問題のうちに入らない」といった類いの問題です。この話をする前に、Node.js はどのように動作し、どう実行されるように設計されているかについて説明しましょう。


Node.js が決してなりえないもの

確かに Node.js はサーバー・プログラムです。しかし、ベースとなる Node.js 製品は決して Apache や Tomcat のようなものではありません。Apache や Tomcat はすぐにインストールできる製品であり、アプリケーションも即座にデプロイすることができ、すぐにサーバーで起動して実行することができます。一方、Node.js は決してそのような製品ではありません。Apache には、PHP モジュールを追加することで動的な Web ページを作成することができるようになり、また SSL モジュールを追加することでセキュアな接続が可能になりますが、それと同様に Node.js にも Node.js コアに追加することができるモジュールの概念があります。Node.js には文字通り何百ものモジュールがあり、Node.js のコミュニティーにおいては日々何十ものモジュールが作成、公開、更新されています。この記事では後ほど、Node.js のモジュール全体について説明します。


Node.js はどのように動作するのか

Node.js はそれ自体が V8 JavaScript を実行しています。これはどういうことでしょうか?サーバーで JavaScript を実行しているのでしょうか?そのとおりです。サーバー・サイドの JavaScript は、これまでクライアント・サイドの JavaScript のみを扱っていたすべての人にとって新しい概念ですが、クライアントで使用しているプログラミング言語と同じ言語をサーバーで使用してみたらどうか、というアイデア自体は現実離れしたものではありませんでした。

では V 8 とは何なのでしょう?V8 JavaScript エンジンは、Google が Chrome ブラウザーのベースとして使用している JavaScript エンジンです。クライアント上で JavaScript によって実際に何が行われているのかを考えるような人はほとんどいませんが、実際には、JavaScript エンジンはコードを解釈して実行しています。Google が開発した V8 は、C++ で作成された超高速のインタープリターです。このインタープリターには、このエンジンをダウンロードして任意のアプリケーションに組み込むことができるという、ユニークな特徴があります。V8 JavaScript エンジンはブラウザーの中でしか実行できないわけではありません。つまり、Node.js は Google が開発した V8 JavaScript エンジンを実際にサーバーで使用するように転用しているのです。これは完璧です!では、既に適切なソリューションを利用できるのに、なぜ新しい言語を作成する必要があるのでしょう。

イベント駆動型プログラミング

プログラマーの多くは、オブジェクト指向プログラミングが完璧なプログラミング・デザインであると信じ込まされ、オブジェクト指向プログラミング以外を使用しないように指導されています。しかし、Node.js はイベント駆動型プログラミング・モデルと呼ばれる方式を利用しています。

リスト 1. jQuery を使用したクライアント・サイドのイベント駆動型プログラミング
// jQuery code on the client-side showing how Event-Driven programming works

// When a button is pressed, an Event occurs - deal with it
// directly right here in an anonymous function, where all the
// necessary variables are present and can be referenced directly
$("#myButton").click(function(){
     if ($("#myTextField").val() != $(this).val())
         alert("Field must match button text");
});

サーバー・サイドは、実際にはクライアント・サイドと何も変わりません。確かに、ボタンが押されることやテキスト・フィールドへ入力されるといったことはありませんが、上位レベルでは、イベントが発生しています。接続が確立され (イベントが発生します!)、その接続を介してデータが受信され (イベントが発生します!)、その接続を介したデータの受信が停止します (イベントが発生します!)。

なぜ、このタイプの設定が Node.js にとって理想的なのでしょう?JavaScript はイベント駆動型プログラミングにとって非常に優れた言語です。なぜなら、JavaScript では匿名関数やクロージャーが使用可能であり、もっと重要な点としては、JavaScript の構文はコーディング経験のあるほとんどの人にとって、おなじみのものだからです。イベントが発生すると呼び出されるコールバック関数は、イベントを捕捉する場所と同じ場所に作成することができます。このように、JavaScript には複雑なオブジェクト指向のフレームワークやインターフェースがなく、何かを過剰に構築してしまう可能性もないため、コーディングや保守が容易です。単純にイベントをリッスンし、コールバック関数を作成すれば、あとはすべてを処理してくれます。


Node.js アプリケーションの例

いよいよ、コードを見てみることにしましょう。ここまでに説明したすべてのことをまとめて、最初の Node.js アプリケーションを作成してみます。ここまでの説明で、Node.js は高トラフィック・アプリケーションの処理に適していることがわかったので、速度を最大にすることを目指した非常に単純な Web アプリケーションを作成してみましょう。上司から渡されたアプリケーションの仕様には、「ランダムな数を生成する RESTful な API を作成すること」とあります。このアプリケーションは入力として、number という 1 つの引数を取る必要があります。そしてこのアプリケーションは、この引数と 0 との間のランダムな数を生成し、その生成された数を呼び出し側に返します。上司はこのアプリケーションは非常に人気が出ると見込んでいるので、50,000 人のユーザーを同時に処理できる必要があります。ではコードを見てみましょう。

リスト 2. Node.js によるランダム数生成プログラム
// these modules need to be imported in order to use them.
// Node has several modules.  They are like any #include
// or import statement in other languages
var http = require("http");
var url = require("url");

// The most important line in any Node file.  This function
// does the actual process of creating the server.  Technically,
// Node tells the underlying operating system that whenever a
// connection is made, this particular callback function should be
// executed.  Since we're creating a web service with REST API,
// we want an HTTP server, which requires the http variable
// we created in the lines above.
// Finally, you can see that the callback method receives a 'request'
// and 'response' object automatically.  This should be familiar
// to any PHP or Java programmer.
http.createServer(function(request, response) {

     // The response needs to handle all the headers, and the return codes
     // These types of things are handled automatically in server programs
     // like Apache and Tomcat, but Node requires everything to be done yourself
     response.writeHead(200, {"Content-Type": "text/plain"});

     // Here is some unique-looking code.  This is how Node retrives
     // parameters passed in from client requests.  The url module
     // handles all these functions.  The parse function
     // deconstructs the URL, and places the query key-values in the
     // query object.  We can find the value for the "number" key
     // by referencing it directly - the beauty of JavaScript.
     var params = url.parse(request.url, true).query;
     var input = params.number;

     // These are the generic JavaScript methods that will create
     // our random number that gets passed back to the caller
     var numInput = new Number(input);
     var numOutput = new Number(Math.random() * numInput).toFixed(0);
     
     // Write the random number to response
     response.write(numOutput);
     
     // Node requires us to explicitly end this connection.  This is because
     // Node allows you to keep a connection open and pass data back and forth,
     // though that advanced topic isn't discussed in this article.
     response.end();

   // When we create the server, we have to explicitly connect the HTTP server to
   // a port.  Standard HTTP port is 80, so we'll connect it to that one.
}).listen(80);

// Output a String to the console once the server starts up, letting us know everything
// starts up correctly
console.log("Random Number Generator Running...");

このアプリケーションを起動する

上記のコードを random.js というファイルにコピーします。このアプリケーションを起動して実行する (そして HTTP サーバーを生成して、ポート 80 で接続をリッスンする) ためには、単純にコマンド・プロンプトから % Node.js random.js を実行します。サーバーが起動されていて実行状態になっている場合に出力される結果を以下に示します。

root@ubuntu:/home/moila/ws/mike# node random.js
Random Number Generator Running...

このアプリケーションにアクセスする

このアプリケーションは起動されて実行状態になっています。現在、Node.js は接続をリッスンしているので、このアプリケーションをテストしてみましょう。ここでは単純な RESTful API を作成したので、Web ブラウザーを使用してアプリケーションにアクセスすることができます。(必ず先ほどのステップを完了した後で) アドレスとして http://localhost/?number=27 を入力します。

ブラウザー・ウィンドウの表示が変わり、0 と 27 の間のランダムな数が表示されるはずです。ブラウザーの再読み込みボタンを押すと、別のランダムな数が表示されます。これで最初の Node.js アプリケーションが完成しました。


Node.js は何に適しているのか

ここまで皆さんは Node.js に関してさまざまなことを学んできたので、「Node.js とは一体何か?」という質問には答えられるようになったかもしれません。しかしそれでもまだ、「どのような場合に Node.js を使用すればよいのか?」という質問が残っているかもしれません。どのような場合に Node.js を使用すればよいかを知っておくことは重要です。なぜなら Node.js には、実によく適した特定の用途があるからです。

Node.js に適した用途

ここまでで理解できたように、大量のトラフィックが想定される場合や、クライアントへの応答前に必要となるサーバー・サイドのロジックと処理が必ずしも大規模ではない場合に、Node.js は非常にうまく機能するように設計されています。Node.js に適した用途の好例を以下に挙げます。

  • RESTful な API

    RESTful な API を提供する Web サービスは、引数をいくつか取って解釈し、レスポンス (通常は比較的少量のテキスト) を組み立ててユーザーに返します。こうした状況には、Node.js はうってつけです。Node.js を使えば、何万もの接続を処理することが可能な Web サービスを作成することができるからです。この Web サービスは、基本的にデータベースの値を参照してレスポンスを組み立てるだけであるため、大量のロジックを必要とすることはありません。送信するレスポンスも受信するリクエストも少量のテキストなのでトラフィック量は多くなく、たとえ Web サービスへのアクセスが非常に多い会社が提供する API であっても、おそらく 1 台のマシンで API への要求を処理することができるでしょう。

  • Twitter のキュー

    ツイートを受信して、それをデータベースに書き込まなければならない Twitter のような会社を考えてみてください。文字どおり毎秒何千件ものツイートが送られてくるため、ピーク時には要求される書き込み回数にデータベースの処理が追い付けなくなる可能性があります。Node.js はこの問題を解決する重要な鍵となります。これまで見てきたように、Node.js は送られてくる何万件ものツイートを処理することができます。Node.js はそれらのツイートを、メモリー内のキューイング・メカニズム (memcached など) に素早く簡単に書き込むことができます。そして、別のプロセスによってそのキューイング・メカニズムからデータベースにツイートを書き込むことができます。この場合の Node.js の役割は、素早くツイートを収集し、書き込みを行うための別プロセスに、収集したツイートの情報を渡すことです。別の設計例として、データベース自体への書き込み処理を試行する通常の PHP サーバーを考えてみてください。ツイートがデータベースに書き込まれるごとに、(データベースの呼び出しはブロッキング呼び出しのため) わずかな遅延が生じます。この設計を実装したマシンでは、データベース処理の遅延のため、送られてくるツイートを毎秒 2000 件しか処理することができないかもしれません。この設計のマシンで毎秒百万件のツイートを処理しようとすると、500 台のサーバーが必要になりますが、Node.js はこのような設計とは異なり、すべての接続を処理し、しかもブロッキングすることはないため、送られてくる限りのツイートを受信することができます。毎秒 50,000 件のツイートを処理できる Node.js を実装したマシンであれば、20 台のサーバーしか必要ありません。

  • テレビ・ゲームの統計データ

    オンラインで「コール オブ デューティ」のようなゲームをしたことがある人であれば、そのゲームの統計データを見たとたん、あることが頭に浮かびます。つまりそうしたゲームでは、そのゲームに必要な統計データを生成するために、ゲームに関する膨大な量の情報を追跡しているはずです。どの時点であれ、そのゲームをプレイしている人々が何百万人もいることを考えると、瞬く間に、生成される情報量が膨大になることは理解できます。こうした状況に適しているのが Node.js です。Node.js はゲームから生成されるデータを取り込んで、最低限の統合を行い、それをキューに入れてデータベースに書き込むことができるからです。ゲームの中で弾丸が何発発射されたかを追跡するために、1 つのサーバー全体を使用することは馬鹿げているように見えます (しかし Apache のようなサーバーを使用する場合には、そうした使い方をするのがサーバーを有効に利用する上での限界かもしれません)。一方、ゲームの統計をほとんどすべて追跡できる 1 つのサーバー (例えば Node.js を実行するサーバーなら、それが可能です) を使用するのであれば、それほど馬鹿げているようには見えません。


Node.js モジュール

当初はこの記事で説明する予定はありませんでしたが、多くの方々の要求に応え、この記事を拡張して Node.js のモジュールと Node Package Manager を簡単に紹介することにしました。Apache を扱っているとだんだん慣れてくるように、Node.js に慣れてくると、モジュールをインストールするとことで Node.js の機能を拡張できるようになります。ただし、Node.js で使用するモジュールは、Node.js の機能を大幅に強化するため、まったくモジュールをインストールせずに Node.js を使用するということはあり得ません。これほどにまで重要になっているモジュールは、今や Node.js 全体に不可欠なものとなっています。

「参考文献」にはモジュールのページへのリンクを挙げてあります。そのページには、利用可能なすべてのモジュールが網羅されています。どんなモジュールが利用できるのか簡単に見てみると、動的に作成されるページを作成するためのモジュール (PHP と似ています)、MySQL を容易に操作できるようにするためのモジュール、WebSockets を使用しやすくするためのモジュール、テキストやパラメーターの解析を補助するモジュール、そしてその他何十ものモジュールがあります。ここではモジュールの詳細については説明しません。この記事の目的はあくまでも、Node.js はさらに詳しく調べるに値するものであるかどうかを判断できるように、Node.js の概要を説明することにあるからです。もし Node.js をさらに詳しく調べることにした場合には、利用可能なモジュールを使ってみることになるのはおそらく間違いないでしょう。

また、Node.js には Node Package Manager (npm) があります。このパッケージ・マネージャーは、皆さんが使用する Node.js モジュールのインストールと管理を行う専用の手段となります。npm は依存関係を自動的に処理してくれるため、インストールすることにしたモジュールを、そのモジュールに必要な要素をすべて含めて、確実かつ適切にインストールしてくれます。また、独自のモジュールを作成することになった場合には、その独自モジュールをコミュニティーに公開する手段も提供してくれます。npm は、インストール済みの Node.js に問題が生じる心配をすることなく、Node.js の機能を容易に拡張するための手段と考えることができます。繰り返しますが、Node.js をさらに詳しく調べることにした場合には、その Node.js ソリューションにとって npm は必須になるはずです。


まとめ

編集者からの注釈

この記事の最初のバージョンが公開されると、この記事で取り上げたさまざまな点に関して、コミュニティーからさまざまな議論が起こりました。著者はその後、それらの議論を踏まえ、この記事を改訂しました。そうした仲間同士の批評や議論はオープンソースの世界には不可欠です。建設的な意見をくださった方々に感謝いたします。

他のすべてのオープンソース・プロジェクトと同様、Node.js は今後も進化を続け、どれほど多くの制約があったとしても、開発者達はそれらの制約を克服する新しいリソースや手法を見つけられるはずです。いつものことですが、読者の皆さんには自ら技術を試してみることをお勧めいたします。

この記事を読み始めるときに、多くの皆さんが持っていた「Node.js とは一体何か?」という質問は、この記事を読み終えたときには答えが出ているはずです。皆さんは、Node.js が何であるかを 2 ~ 3 の明確で簡潔な文で説明できるようになっているはずです。それができる人は、世界中のほとんどすべてのプログラマーよりも一歩先を行っていると言えます。Node.js について私が話をした多くの人達は、Node.js が正確に何をするものなのかについて誤解していました。そうした人達は、当然のことながら、Apache の発想で考えてしまっています。つまり、サーバーはアプリケーションであり、そこに HTML ファイルを置けばすべてが問題なく動作する、と考えています。ほとんどのプログラマーは Apache と、Apache で行われることに慣れているため、Node.js を説明する最も簡単な方法は、Apache と Node.js を比較することです。この比較によれば、Node.js は (いくつかのモジュールを使用すれば)、Apache ができることであれば何でもできるプログラムです。Node.js は それだけにとどまらず、拡張可能な JavaScript プラットフォームを構築できることから、はるかに多くのことを実現することができます。

この記事では、Node.js がどのようにして非常にスケーラビリティーの高いサーバーを実現するかを説明しました。Node.js は、Google による超高速の JavaScript エンジンである V8 エンジンを使用しています。また、Node.js はイベント駆動型の設計を使用することで、コードを最小限にとどめ、読みやすいものにしています。これらの要因すべてにより、Node.js は目的を達成することができました。つまり、圧倒的にスケーラブルなソリューションを比較的容易に作成できるようになったのです。

Node.js とは何かを理解するのと同じくらい重要なことは、Node.js とは何でないかを理解することです。Node.js は PHP を使用した Web アプリケーションを即座にスケーラブルにする目的のために、単純に Apache を置き換えるものではありません。それは事実とまるでかけ離れています。Node.js はまだ登場してから日が浅いですが、非常に速く成長していることや、コミュニティーがとても活発に活動していること、そして優れたモジュールが大量に作成されていることなどを考えると、この成長著しい製品が 1 年以内に皆さんのビジネスに登場することも考えられます。

参考文献

学ぶために

  • Node.js のホームページはアプリケーションについて学ぶための出発点です。
  • ここから Node.js をダウンロードしてください。Python も必要になります。
  • Node.js API のページを閲覧してください。構文はリリースごとに変更される可能性があるため、このページの API が、皆さんがダウンロードしたバージョンと同じかどうかを調べてください。
  • Node.js のモジュールのページを参照してください。このページには Node.js で使用するためのモジュールがすべて記載されています。
  • お使いの Node.js にインストールされている機能を容易に拡張するために npm を検索してください。
  • developerWorks の Technical events and webcasts で最新情報を入手してください。
  • Twitter で developerWorks をフォローしてください。
  • オープンソース開発者にとって関心のある、世界中で今後開催される会議や業界展示会、ウェブキャスト、その他のイベントについて調べてみてください。
  • developerWorks の Open source ゾーンをご覧ください。オープンソース技術を使った開発や、IBM 製品でオープンソース技術を使用するためのハウ・ツー情報やツール、プロジェクトの更新情報など、豊富な情報が用意されています。
  • 無料の developerWorks On demand demos でIBM とオープンソース技術、そして製品機能を学んでください。

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source
ArticleID=664950
ArticleTitle=Node.js とは一体何か?
publish-date=06092011