ページ

2012-02-26

細かすぎて伝わらない Node v0.7.5 の変更点

こんにちは、summerwind です。

今日は「東京Node学園 4時限目」ということで、Node.js ハッカソンにきています。
今回の会場は @nifty エンジニアサポートさんにご提供いただきました。お菓子の差し入れなどもいただきありがとうございます!

さて、会場で Jxck 先生に「ぜひブログにもなんか書いて」と言ってもらったので、今回は先日リリースされた Node v0.7.5 の変更点について、いくつか簡単にピックアップして紹介したいと思います。全ての変更点については日本語訳した ChangeLog をご確認ください。

crypto モジュールに getDiffieHellman() 関数が追加されました

まずは、crypto モジュールに追加された getDiffieHallman() 関数を紹介したいと思います。
従来から crypto.createDiffieHellman() 関数を利用することで Diffie-Hellman 方式の共有鍵を生成することはできましたが、 今回追加された getDiffieHellman() を利用すると、より容易に共通鍵を用意することができます。

マニュアルには下記のような使い方が記載されています。

var crypto = require('crypto');
var alice = crypto.getDiffieHellman('modp5');
var bob = crypto.getDiffieHellman('modp5');

alice.generateKeys();
bob.generateKeys();

var alice_secret = alice.computeSecret(bob.getPublicKey(), 'binary', 'hex');
var bob_secret = bob.computeSecret(alice.getPublicKey(), 'binary', 'hex');

/* alice_secret and bob_secret should be the same */
console.log(alice_secret == bob_secret);

実際のコードの変更内容はコミットログで確認することができます。コードが気になる方はぜひこちらもご確認ください。

QueryString.parse() を高速化しました

見出しの通り、querystring モジュールのパース処理が高速化しました。
具体的には split() や join() を利用してパラメータのキーと値を処理していた部分を、indexOf() と substring() の処理に置き換えたことで、高速化したようです。短くて分かりやすいコミットログもあわせてご確認ください。

#2762 net モジュールの close 関数にコールバックを追加しました

net モジュールの close() 関数がコールバックを引数にとることができるようになりました。
これにより、HTTP サーバーや TCP サーバーが終了する際に指定の処理の実行が可能になります。
追加の発端になった Issue #2762 を見ると、開いているポートを探すためのサンプルコードがのっていたりしていて興味深かったです。ちなみにコミットログはこちらになります。

'make test' 時に src/ と lib/ に対して JSLint が実行されるようになりました

make test 時に JSLint が自動実行されるようになりました。
コミットログを見ると、Ben Noordhuis が「1日20回ぐらいビルドしてるんだけど、こいつのせいで30秒ぐらいロスするから、戻せ」って書いていたりしていて、ちょっと笑ってしまいました。

こんな感じで、Node v0.7.5 では色々な細かい変更がなされました。
コミットログまで追って見ると、実際のコードの変更や、開発者同士のやりとりなどが見れてとても勉強になるのでオススメです。
そろそろ次の安定版である v0.8.0 のリリースも近づいてきているようなので、今後の更新も楽しみにしたいと思います。

それではまた。

2011-11-12

Cluster

Node.js v0.6 の新機能として cluster モジュール が導入されました.cluster モジュールは,HTTP を含めた TCP 接続を複数の子プロセス (ワーカプロセス) で処理することにより,特にマルチコア環境でのスループット (リクエスト/秒) を向上するための機能です.
 
しかし,ドキュメントにはその使い方が書かれているだけで,どのように実現されているかは書かれていないので,ここで簡単に紹介しておきます.
 
Node.js のクラスタ機能は v0.5.10 で突然コマンドラインオプションとして導入されましたが,直後の「東京 Node 学園祭 2011」が行われた頃にはコマンドラインオプションは廃止されて cluster モジュールによって API が提供されるようになり,その翌週の v0.6.0 リリース数時間前にはその API が変更されるというドタバタぶりでしたw
 
早速複数のプルリクエストが届いているなど,現時点では API が安定しているとは言い難い状況ですが,ここで紹介する基本的な実現方式については大きく変わることはないものと考えられます.
 

ソケットの基本

まずは,基本となるソケットについて復習しておきましょう.
 
通常,サーバサイドのアプリケーションは次の手順でソケットを利用します (引数の詳細やエラーチェック等は省略,ブロッキング・ノンブロッキング等は本エントリでは省略します).
 
listening = socket(...); // ソケットをオープン
bind(listening, ...);    // ローカルアドレス&ポートを割り当て
listen(listening, ...);  // リスニングソケットに変換
for (;;) {
    connected = accept(listening, ...); // 接続済みソケットを返す
    ...
    close(connected);
}
 

ここでは 2 種類のソケットが登場します.ひとつはクライアントからの接続を待ち受けるためのソケットで,ここでは「リスニングソケット」と呼びます.もうひとつは実際にクライアントとの接続を表すソケットで,ここでは「接続済みソケット」と呼びます.
 
socket(), bind(), listen() でリスニングソケットを準備して,accept() でリスニングソケットに届いた接続済みソケットを取得します.
 
接続済みソケットからクライアントの要求を受信したり,結果を送信するなどしてクローズすることで,一つのクライアントに対する処理が完了します.これを繰り返すことで,単純なサーバを実現することができます.
 
ただし,これではクライアントを一つずつしか処理することができません.同時に複数のクライアントを処理するには,一工夫が必要です.Node.js の場合は,accept()select() 等のシステムコールによって「多重化」するイベントループを使うためにこの問題はありませんが,しばらくの間それは忘れましょう.
 

フォーク型

複数のクライアントからの接続を処理するために,古くからよく使われた素朴な方法が,クライアントからの接続ごとに fork() して新しいプロセスを作成するというものです.
 
 
listening = socket(...); // ソケットをオープン
bind(listening, ...);    // ローカルアドレス&ポートを割り当て
listen(listening, ...);  // リスニングソケットに変換
for (;;) {
    connected = accept(listening, ...); // 接続済みソケットを返す
    if (fork() == 0) {
        // 子プロセス (親プロセスとは並行に実行される)
        ...
        exit(0);
    }
    // 親プロセス
    close(connected);
}
 

子プロセスはソケット (ファイル記述子) を親プロセスから引き継ぎますから,接続済みソケットを使ってクライアントと送受信することができます.接続済みソケットを標準入出力に設定して exec() (現在のプロセス上で別のプログラムを実行) すれば,CGI の動作になります.
 
フォーク型は単純であるため,スレッドが普及する以前 (20 年前とか) に Unix 上で作られた多くのサーバアプリケーションで利用されていました.しかし,クライアントからの接続のたびにプロセスを起動するオーバーヘッドが大きいため,多くのクライアントを扱うことが難しいという問題がありました.
 
より多くのクライアントをサポートするには,あらかじめ子プロセスを起動 (プリフォーク) しておく必要があります (本エントリではスレッドは扱いません).以下ではその方法を見ていきましょう.
 
なお,以下では親プロセスをマスタ,子プロセスをワーカと呼びます.
 

ゲートウェイ型

一つ目の方法は,クライアントとワーカの間で送受信されるデータを,マスタが間に入って転送するゲートウェイ方式です.マスタはクライアントとってはサーバ,ワーカに対してはクライアントのように振る舞います.各ワーカはそれぞれ独自のポート番号でマスタからの接続を待ち受けます.
 
// マスタ
listening = socket(...); // ソケットをオープン
bind(listening, ...);    // ローカルアドレス&ポートを割り当て
listen(listening, ...);  // リスニングソケットに変換
for (;;) {
    connected = accept(listening, ...); // 接続済みソケットを返す
    worker = socket(...);  // ワーカとの通信用のソケットをオープン
    connect(worker, ...);  // ワーカに接続
    ...                    // クライアントとワーカの間でデータを転送
    close(worker);
    close(connected);
}
 

おっと,これでは最初の例と同じように,同時に一つのクライアントしか接続できませんね.実際には,accept() もワーカとの接続や送受信も,全て多重化されてイベントループの中で行われるということにしてください.
 
ともあれ (JW),この方法の場合,connect() で接続するワーカをラウンドロビンなどの方法で切り替えることにより,複数のワーカにクライアントからの処理を分散することができます.新しいクライアントをどのワーカで処理させるか (ロードバランシング) はマスタが判断することになります.
 
しかし,全てのクライアントからの送受信データがマスタを経由するため,マスタのスループットが全てのワーカを含めた全体の上限になってしまいます.実際には,この方法を親プロセスと子プロセスの間で利用することはあまりなく,複数のサーバマシン間で処理を分散するためのリバースプロキシ等で使われることが多いでしょう.
 
Node.js 関連では Nodejitsu の node-http-proxy でこの方法が使われています.
 

接続済みソケット共有型

ソケット (ファイル記述子) は,Unix ドメインソケットやパイプを通じてプロセス間で受け渡すことができます.これを利用して接続済みソケットをマスタからワーカに受け渡すことで,接続した後のクライアントとの送受信はワーカに任せることが実現できます.
 
// マスタ
listening = socket(...); // ソケットをオープン
bind(listening, ...);    // ローカルアドレス&ポートを割り当て
listen(listening, ...);  // リスニングソケットに変換
for (;;) {
    connected = accept(listening, ...); // 接続済みソケットを返す
    ... // connected をワーカに転送する
    close(connected);
}
 

先のゲートウェイ方式方式とは異なり,クライアントからの接続時に接続済みソケットがワーカに渡された後では,もうマスタはクライアントとの通信に関与しません.ですから,ゲートウェイ方式に比べると接続済みソケット共有型の方がずっと効率的といえるでしょう.複数のワーカがある場合に,どのワーカに接続済みソケットを渡すか (ロードバランシング) はマスタが判断することになります.
 
2013/05/19 追記
Node.js の cluster モジュールは、v0.11.2 から Unix 系 (非 Windows) プラットフォームではこの方式がデフォルトになりました。マスタプロセスはラウンドロビン方式でワーカプロセスに接続済みソケットを渡します。明示的に「接続済みソケット共有型」を利用するには、cluster.schedulingPolicycluster.SCHED_RR を指定します (または、NODE_CLUSTER_SCHED_POLICY 環境変数に rr を指定します)。
 

リスニングソケット共有型

プロセス間で受け渡すことができるソケットは接続済みソケットには限りません.リスニングソケットもまた受け渡すことができます.
 
// マスタ
listening = socket(...); // ソケットをオープン
bind(listening, ...);    // ローカルアドレス&ポートを割り当て
... // ソケットをワーカに渡す
 
これまでの例では listen()accept() はマスタで実行していましたが,この方式ではワーカがそれを実行します.
 
// ワーカ
...                      // マスタからソケットを受け取る
listen(listening, ...);  // ソケットをリスニングソケットに変換
for (;;) {
    connected = accept(listening, ...); // 接続済みソケットを返す
    ...
    close(connected);
}
 

この場合,同じリスニングソケットに対して複数のワーカが同時に接続を待ち受けることになります.実際にクライアントからの接続が着信した場合に,どのワーカがそれを受け取るかは OS カーネルによって決められます.マスタは関与しません.そのため,この方法は「カーネルによるロードバランシング」と呼ばれることがあります.
 
この方法では,マスタは初期化時にリスニングソケットを準備するだけです.クライアントとの間のやり取りは,接続から送受信まで完全にワーカとの間で直接行われます.マスタは一切関与しません.ですから,これまでの方法の中でもっとも効率がいいといえるでしょう.
 
Node.js v0.6 で導入された cluster モジュールは,この方法を採用しています.
 
2013/05/19 追記
この方法では一部のワーカプロセスに接続が偏りやすいため、v0.11.2 から Unix 系 (非 Windows) プラットフォームでは前述の「接続済みソケット共有型」がデフォルトになりました。v0.11.2 以降で「リスニングソケット共有型」を利用するには、cluster.schedulingPolicycluster.SCHED_NONE を指定します (または、NODE_CLUSTER_SCHED_POLICY 環境変数に none を指定します)。
 

Node.js cluster モジュールの実際

それでは,実際に Node.js の cluster モジュールがどのように動作するか,簡単に見てみましょう.以下は cluster モジュールを使用しない単純な HTTP サーバの例です.
 
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, 'localhost');
 
これを cluster モジュールを使わず直接実行すると,http.Server (実際には net.Server) の listen() メソッドは,内部的にソケットの socket()bind(), listen()accept() を呼び出します.
 
一方,次のように cluster モジュールを使用すると,
 
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // マスタ
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork(); // ワーカを起動
    }

    cluster.on('death', function(worker) {
        console.log('worker ' + worker.pid + ' died');
    });
} else {
    // ワーカ
    http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Hello World\n');
    }).listen(1337, 'localhost');
}
 
ワーカとして実行される部分のコードは,先ほどの cluster を使わない例と全く同じですが,http.Serverlisten() メソッドの動作が変わります.ワーカとして実行されているプロセスでは,http.Serverlisten() メソッドはマスタに"localhost"1337 番でバインドされたソケットをよこせ」という要求 (プロセス間通信) を行います.そこでマスタは socket(), bind() を呼び出してソケットを作成し,ワーカに転送します.ワーカはそのソケットに対して listen(), accept() を実行します.
 
別のワーカが同様に「"localhost"1337 番でバインドされたソケットをよこせ」とマスタに要求すると,マスタは先ほど作成したソケットを転送します.これにより,複数のワーカ間でリスニングソケットが共有されます.
 
このように,Node.js の cluster モジュールを使うと,従来とほぼ同じコードで複数プロセスによる負荷分散を効率よく実現することができます.皆さんも是非 cluster モジュールを使ってみてください.
 
 
なお,@hoakobera さんによる「Node.js の Cluster のベンチマークをとってみた」も併せてどうぞ.

2011-11-05

Node v0.6.0

このエントリは Node.js 公式ブログの「Node v0.6.0」を翻訳したものです.

 
私たちは三番目となる安定版の Node v0.6 をアナウンスすることをうれしく思います.
 
v0.6 系の全てのリリースで JavaScript,C++,そしてバイナリインタフェースは凍結されます.
 
v0.4 と v0.6 の主要な違いは
 
  • ソケットに I/O 完了ポートを使用する Windows のネイティブサポート.
  • 統合されたマルチプロセッサ上のロードバランサ.docs
  • 改善された Node インスタンス間の IPC.docs
  • 改善されたコマンドラインデバッガ.docs
  • zlib への組込バインディング.docs
 
Windows をサポートするために,私たちはコアアーキテクチャの多くを再構築しました.それが Unix システム上でのパフォーマンスを低下させるという恐れがありましたが,それは杞憂でした.Linux システムでのデモによるベンチマークはこの通りです:
 
v0.4.12 (linux)v0.6.0 (linux)
http_simple.js /bytes/1024  5461 r/s 6263 r/s
io.js read 19.75 mB/s 26.63 mB/s
io.js write 21.60 mB/s 17.40 mB/s
startup.js 74.7 ms 49.6 ms
 
http と io は数値が大きい方が,startup は小さい方が優れています.http ベンチマークは 10Gbit ネットワーク上のサーバに 3 台のマシンで 600 クライアントの負荷を生成しました.
 
以前のバージョンの Node v0.4 は,Windows では Cygin 上でしか動きませんでした.そのため,ネイティブ API を目標とすることにより,劇的な改善を果たしました.同じマシンでのベンチマーク:
 
v0.4.12 (windows)v0.6.0 (windows)
http_simple.js /bytes/1024  3858 r/s 5823 r/s
io.js read 12.41 mB/s 26.51 mB/s
io.js write 12.61 mB/s 33.58 mB/s
startup.js 152.81 ms 52.04 ms
 
私たちはこれが Windows ポートのよい中間段階だと考えています.すべきことはまだあります.たとえば,MS VisualStudio でアドオンモジュールをビルドする方法を私たちはまだ提供していません.この後のリリースに作業は続きます.
 
これからのリリースサイクルは劇的に短縮されます.1 月には新しい安定版が出ると期待してください.私たちは Chrome および V8 の 6 週間サイクルと同期してリリースしたいと望んでいます.
 
コード,テスト,ドキュメント,そしてバグを報告してくれた全ての貢献者に感謝します.
 

2011-10-28

東京Node学園祭 2011 明日開催!

東京Node学園祭 2011 よりお知らせ

東京Node学園祭 2011 参加者の皆様 Node.js 日本ユーザグループ 東京Node学園祭 2011 実行委員会です。 いよいよ明日、10月29日が開催日となります!

当日学園祭を楽しめていただけるよう、 会場の注意点などを掲載いたします。 ご一読よろしくお願いします :)

今回は以下の内容についてお知らせいたします。

  • 会場に関するお知らせ
    • 場所
    • 開場時間
    • 受付
    • ノベルティグッズのお渡し
    • 入館用パスのお渡し
    • ネットワークのご利用について
    • 電源のご利用について
    • 会場の撮影について
    • お昼について
    • 退場時の注意
  • 後夜祭について
    • 場所
    • 移動方法
    • 開場時間
    • 受付
  • Twitterのご利用について
    • 公式アカウント
    • 当日のハッシュタグ

会場に関するお知らせ

  • 場所

    場所はYahoo様となります。

  • 住所

    〒107-6211 東京都港区赤坂9-7-1 ミッドタウン・タワー Yahoo! JAPAN 11F

  • 最寄駅
    • 都営大江戸線 六本木駅
    • 東京メトロ日比谷線 六本木駅
    • 東京メトロ千代田線 乃木坂駅
    • 東京メトロ南北線 六本木一丁目駅
  • 詳しくは、以下サイトのリンクをご確認ください。(マップが確認できます)

    http://nodefest.jp/2011/access.html

  • 開場時間

    午前 10:00となります

  • 受付

    2F受付にて、チケットのご確認をさせていただきます。 Doorkeeperでご購入いただいたチケットを受付スタッフにご提示ください。 チケットはiPadなどのデジタルデバイスに表示するか、紙への印刷をしてください。 受付後、スタッフが皆様を会場に誘導いたします。

  • ノベルティグッズのお渡し

    11Fにてノベルティグッズをお渡しいたします。 後夜祭のご参加に必要なカンファレンスバッグを含みます。

  • 入館用パス

    スタッフが受付後、チケットを確認できましたら、入館用パスを発行いたします。 入館用パスを胸元に貼っていただく必要がございます。

  • ネットワークのご利用について

    当日、参加者の皆様がご利用いただけるAPを用意し、 SSID及びPASSについてご連絡いたします。 ただし、利用人数に限りがございます。 ご自分でemobile/WiMAXなどの無線インターネット回線端末を お持ちいただけると幸いです。

  • 電源のご利用について

    会場の電源容量は予め決まっており、想定されている以上の機器を 利用することはできません。独自にタップを使って電源の口を増設される、 電源を大量消費する行為については自粛をお願いいたします。 また、できるだけ譲り合って電源をご利用いただけますと、 学園祭を最後まで皆様揃ってお楽しみいただけることと思います。 よろしくお願いいたします。

  • 会場の撮影について

    受付のある2F、及び 11F の廊下は撮影が禁止となっております。 当日カンファレンスが行われる11Fセミナールームでは撮影が行えます。 撮影に関し不明な点がございましたらスタッフまでご質問ください。

  • お昼について

    当日、参加者の皆様にはお弁当をお配りいたします。 途中の入退場は原則できませんので、お昼はお弁当でお済ませ下さい。

  • 退場について

    退場の際、入場時にお渡しした入館用パスをお返しいただく必要がございます。 受付スタッフまでお返しください。


後夜祭について

  • 後夜祭とは

    東京Node学園祭終了後、後夜祭(アフターパーティー)を開催いたします。 開催費用は参加チケット代金に含まれておりますので、安心してご参加いただけます。 気になるnoderの方とお話するチャンスです。

    • 場所

      居酒屋 小松となります。詳しくはリンクをご確認ください。

      http://r.tabelog.com/tokyo/A1307/A130701/13060057/

    • 移動方法

      担当スタッフが皆様を誘導し、会場にご案内いたします。

    • 開場時間

      19:00 - 21:00 の 2時間となります。

    • 受付方法

      会場に入場する際、学園祭受付時にお渡ししたノベルティグッズの カンファレンスバッグの有無を確認いたします。 受付担当スタッフにお見せください。


Twitterのご利用について

  • 公式アカウント

    https://twitter.com/#!/nodefest です。 当日のご案内、会場での出来事などツイートいたします。 フォローしていただけると東京Node学園祭をよりお楽しみいただけると思います。

  • 当日ハッシュタグ

    #nodefest が当日利用するハッシュタグとなります。 セッション中のツイートなど、ハッシュタグをつけていただきますと、 スタッフや学園祭に参加しているnoderの皆様が捕捉し、思わぬリプライを もらえるかもしれません :)

以上です。当日皆様と会場でお会いできることを楽しみにしております!

2011-10-24

東京Node学園祭 2011 開催まであと5日!

東京Node学園祭 2011 参加者の皆様 Node.js 日本ユーザグループ 東京Node学園祭 2011 実行委員会です。 開催まであと5日となりました。今回は以下の内容についてお知らせいたします。
  • チケット販売締め切りについて(ブログのみ掲載)
  • 会場について
  • セッションのスケジュールについて
  • アフターパーティのご案内

チケット販売を締めきりました

チケットについては売り切れました。

東京Node学園祭 参加者向けのチケットは完売いたしました。 ご購入をご希望されていたた方には大変ご迷惑をおかけいたしました。 ニコニコ生放送にて当日のカンファレンス内容を生で配信する予定です。 詳細は追ってご連絡いたします。


会場について

開催会場はYahoo様となります。

  • 場所
  • 受付方法
    • 受付は入り口よりスタッフがご案内致します。 DoorKeeperのチケットをスタッフに提示してください。 (iPad,iPhone,ノートPCなどの端末に表示、及び印刷などの方法でスタッフが チケットを確認できる形でご提示ください)
  • ご注意
    • 入退場について

      当日会場から退場した場合、再入場は行えません。 お昼についてはお弁当をご用意しております。 また自動販売機が設置されており飲み物の購入が可能です。

    • 参加者の皆様による会場撮影について

      当日会場の撮影については、撮影可能な場所が限られます。 会場の内部での撮影は問題ありません。会場外部(フロアから外)は 撮影が禁止となっております。ご了承ください。

    • 会場でのセッションをネットで配信します

      当日、ニコニコ生放送にてセッションの内容を配信いたします。

  • スタッフ及びメディアによる会場内撮影について

    後日のレポート用記事のため、スタッフが会場を撮影します。 またメディアの方による会場撮影も行われる予定です。 ご了承ください。


セッションのスケジュールについて

  • カンファレンスのセッションは以下の予定で行われます。
  • スケジュールについて変更が行われる恐れがあります。ご容赦ください。
  • 最新のセッションスケジュールについては【こちら】をご確認ください。
時間帯 セッションタイトル スピーカー
10:00-11:00 開場
11:00-11:10 イントロダクション meso
11:10-12:30 基調講演 Ryan Dahl
12:30-13:30 昼食(お弁当をご用意しております)
13:30-14:00 LiveCoding for beginner Jxck(Nodejs_jp)
14:00-14:30 Node.jsでブラウザメッセンジャー / YOLPとRealtime Geo 石澤基、濱邉将太、栗山太希、中村友一 (ヤフー株式会社)
14:30-14:40 休憩
14:40-15:10 ピグライフとnode.js 名村卓 (株式会社サイバーエージェント)
15:10-15:40 ngCoreにおけるNode.js 篠崎祐輔 (株式会社ディー・エヌ・エー)
15:40-15:50 休憩
15:50-16:50 Socket.IOについて Guillermo Rauch
16:50-17:00 休憩
17:00-18:30 LT大会
18:30-19:00 閉幕
19:00- 後夜祭(アフターパーティー)

アフターパーティーについて

居酒屋小松にてアフターパーティーを開催します! 参加費はチケットに含まれているため、チケットをお持ちの方は 無料で参加できます。ふるってご参加ください!

居酒屋小松

  • 場所
    • リンク先をご確認ください。 【食べログ: 居酒屋 小松】

      当日スタッフがカンファレンス会場からアフターパーティー会場へ 先導し、皆様をご案内いたします。

2011-10-23

Node にまつわる良くある質問

追記

いくつか誤植を修正しました。

  • 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

2011-10-20

今すぐ「GitHub で」フォローすべき Node.js 界のスーパーエンジニア

こちらでははじめまして,koichik です.
Jxck によるエントリ:
では,Node.js 自身を始め,npmSocket.IOExpress といった著名なプロダクトの作者が紹介されました (筆者を除く).彼等は Node.js の世界を大きく広げることに貢献している,文字通り「本当の」スーパーエンジニアです.
しかしながら,Node.js の世界に集うスーパーエンジニアは彼等ばかりではありません.著名なモジュールを作ってはいなくても,Node.js の品質改善や機能強化などで貢献している人達も大勢います.そこで今回は,Node.js の世界を深化させているスーパーエンジニアを 10 人紹介します.
とはいえ,彼等の中には Twitter をほとんど活用していない人もいます.IRC が普及しているせいか,日本に比べると技術的な話題で Twitter が使われることは少ないようです.しかし,「フォロー」は決して Twitter の専売特許ではありません.単なる公開リポジトリではなく,開発者のための SNS といっても過言ではない GitHub にもフォローの機能があります.スーパーエンジニアならではの活動を拝見するには,Twitter 以上に GitHub でのフォローが効果的です.
それでは 10 人のスーパーエンジニアを紹介しましょう.

piscisaureus (Bert Belder)

Node.js の次期安定版となるバージョン 0.6 の目玉は Windows サポートの強化です.その鍵となるのが Windows と Unix の API を抽象化するコンポーネントである libuv です.Bert は libuv の「Windows パート」における中心人物で,Node.js コミッタの一人です.
彼は以前から Node.js の Cygwin 対応や MinGW 対応など,Node.js を Windows で利用するための作業を一手に担ってきました.コミット数では Ryan に次いで 2 番目ということからも,その貢献度を知ることができます.
ホスティングサービスを提供する RackSpace 社勤務で,ほとんどフルタイムで Node.js の開発に専念しているようです. [11/29 追記] Cloud9 IDE に移ったようです.
ちなみに ID の piscis は「魚」,aureus は「黄金」という意味らしいです.金魚……でしょうか?

bnoordhuis (Ben Noordhuis)

Node.js コミッタの一人で,libuv における「Unix パート」の中心人物です.Ben は低水準から高水準まで驚くほど幅広く,かつ深い知識の持ち主で,バイタリティにあふれ,その上細かい配慮も欠かさないという,なんとも素晴らしい人物です.詳しいプロフィールを公開していないのでどういう経歴の持ち主なのか不明ですが,元々は Python をやっていたようです.
前述の Bert と同じオランダ在住で,連日 IRC で会話しながら仲良く Node.js/libuv の開発を続けています.日本時間のお昼過ぎになると二人揃ってベッドに向かうため,他のメンバーから「同じベッドで寝てるのか?」などと突っ込まれるほどです (笑).
日本人ならお世話になることが多そうなモジュール,node-iconv の作者でもあります.

pquerna (Paul Querna)

Paul はNode.js のコミッタであると同時に (というよりずっと以前から),Apache HTTP Server (httpd) のコミッタでもあります.OpenSSL にも詳しく,Node.js の SSL/TLS サポートがバージョン 0.3 系で大幅に改善したのは彼の貢献によるものです.
OpenSSL は Node.js のようなシングルスレッドで非同期 I/O の環境を想定していない部分があるため,Node.js での利用は少々トリッキーなことをしています.そのため,Paul が取り組んでいるのが Selene という非同期 I/O に適した SSL/TLS ライブラリです.これが完成すれば,Node.js だけでなく EventMachine などでの SSL/TLS 実装がさらに改善すると期待されます.
前述の Bert と同じホスティングサービスを提供する RackSpace 社勤務です.

igorzi (Igor Zinkovsky)

今年の 6 月末,Microsoft 社が Node.js を Windows へ移植するために支援するというニュースがあったことを覚えているでしょうか? そのために Microsoft から二人の開発者が Node.js コミュニティにやってきました.その一人が Igor で,libuv のコミッタです.
なのですが,週末でも IRC に浸っていることもあるなど,社命だけで取り組んでいるようには見えません.普通に好きでやってるんだなぁという感じです.Node.js の Windows 版実行ファイルである node.exe は,主に彼と Bert の貢献によってできているといっていいでしょう.
[2011/10/26 追記] Igor が 8 人目の Node.js コミッタになりました。

HenryRawas (Henry Rawas)

Igor と同じく Microsoft のエンジニアです.が,彼の方はすでに Node.js から離れているかもしれません.それなら取り上げるなよって気もしますが,丁度10人にするために…… すみません.

indutny (Fedor Indutny)

SSL/TLS 関連仕様である NPN (Next Protocol Negotitation) と SNI (Server Name Indication) の実装,そして最近になって劇的に機能強化された組込デバッガなど,ちょっと目の付け所が違うところで貢献しているのが Fedor です.Node.js コミッタ以外で一番コミット数が多いのが彼です.最近は libuv へも貢献しています.
とてもフレンドリーな人柄のようで,連日 IRC で他のメンバーに話しかけ続けています.ロシア在住で,前回紹介された indexzero 率いる Nodejitsu の一員です.
[2012/01/10 追記] Fedor が 9 人目の Node.js コミッタになりました。

pgriess (Peter Griess)

Node.js を構成する主要なコンポーネントの一つが HTTP Parser で,Node.js 以外にも多数のプロダクトから利用されている,定評あるものです.その HTTP Parser に貢献しているのが Peter です.node-msgpacknode-websocket-client など,ネットワークプロトコル関連のプロダクトを多くリリースしています.Facebook 勤務です.

mraleph (Vyacheslav Egorov)

Node.js を支えている最重要コンポーネントと言えるのが JavaScript の実行環境である Google V8 です.Vyacheslav (通称 Mr.Aleph) はロシア在住の Googler で,V8 の中の人です.当然ながら V8 のパフォーマンスに詳しく,Node.js でパフォーマンスに関する話題があると,GitHub 上に限らず IRC でも ML でもアドバイスをしてくれます.筆者が Twitter に日本語でつぶやいたことにも (英語で) 返事をくれたことがあります.
現時点の JavaScript (ES5) はバイト列を扱うことができないため,Node.js では独自の Buffer というクラスを提供しています.これは配列のように添え字でアクセスできるのですが,C++ で実装されているため,以前は V8 の最適化が働きませんでした.Mr.Aleph はこれを改善し,Buffer を配列並みに高速にアクセスできるようにしてくれるなど,Node.js と V8 の橋渡しをしてくれています.コワモテです (笑).

mnot (Mark Nottingham)

Node.js の http モジュールの API ドキュメントを見ると,トレーラと呼ばれるボディより後ろに加えられるヘッダや,Expect: 100-continue など,「HTTP にそんなものがあったんだ?」と思うような,マイナーどころか誰も知らないであろう機能が実装されていることに気づきます.これらは Mark の貢献によるものです.
通常,我々が HTTP の仕様を調べる時は RFC を参照します.現在の最新版 (といっても,既に 10 年以上経過しています) は HTTP/1.1 (RFC 2616) ですが,IETF ではその改訂を HTTPbis というワーキンググループ (WG) で進めています.彼はその WG のチェア,つまりとりまとめをしている人です.どうりでマイナーな機能まで詳しいわけですね.
GitHub の課題で HTTP プロトコルに関する問題があると,質問しなくても彼が答えてくれることがあります.なんという贅沢……
前述の Bert や Paul と同じ RackSpace 勤務です.

jed (Jed Schmidt)

ジェッドは日本在住の翻訳家で,きわめて早期から Node.js に貢献してきました.日本の Node.js コミュニティでも最初のミートアップ (Node 飲み会) を主催してくれたり,海外の Node.js コミュニティとの橋渡しをしてくれたりしています.
Node.js といえば非同期プログラミングですが,初期の Node.js では現在とは異なり Promise (Java の Future と似た API,jQuery にも導入された Deferred の原型) を使った今以上に面倒なものでした.それがより洗練される過程で大きなインスピレーションを与えたのがジェッドの (fab) です.(fab) を見ると,JavaScript の奥深さというものをうかがい知ることができます.というか,筆者にはすんなりと読めませんでした.心より恥じる.あれが JavaScript…… だと?

ということで 10 人のスーパーエンジニアを紹介しました.
Apache HTTP Server や V8 の中の人,さらには HTTP の RFC 作ってる人まで,なんともすごい人達の貢献によって Node.js は支えられていることが分かります.ワールドワイドで人気のあるプロダクトってこういうことなのかということを改めて感じました.彼等の書くコードやコメントには参考になることがたくさんあります.是非彼等を「GitHub で」フォローしてみてください.
前回紹介された 10 人の GitHub アカウントも以下に載せておきます.TJ の驚くべきアウトプットの多さ,Isaac の課題をクローズする電光石火の速さ (笑) などは,Twitter でフォローしても味わうことができません.彼等もまた「GitHub で」こそフォローすべきスーパーエンジニアと言えるでしょう (筆者を除く).
  • HOME
  • ABOUT
このページの先頭へ