ページ

ラベル node.js の投稿を表示しています。 すべての投稿を表示
ラベル node.js の投稿を表示しています。 すべての投稿を表示

2012-07-11

「東京Node学園祭 2012」スポンサー公募について

Node.jsのカンファレンス「東京Node学園祭 2012」では、以下の内容でスポンサーを募集しております。
下記枠組みに捕らわれないものも受け付けておりますので、まずはお気軽にお問い合わせください。
(7/19追記)Platinumスポンサーについての記述を追加いたしました。
(9/8追記)スポンサーの公募は全て締め切らせていただきました。多数のご応募ありがとうございました。

スポンサーシップの概要

  • Sliverスポンサー(10万円)
    • Webサイトにバナー(小)を掲載
    • チラシやノベルティの配置(持ち込み)
    • プレスリリースにスポンサー名を記載
    • パンフレットへの広告枠(小)
    • 招待枠: 2名
  • Goldスポンサー(30万円)
    • Webサイトにバナー(大)を掲載
    • チラシやノベルティの配置(持ち込み)
    • プレスリリースにスポンサー名を記載
    • パンフレットへの広告枠(大)
    • 招待枠: 5名
  • Platinumスポンサー(お問い合わせください)
    • セッション枠
    • Goldスポンサーの上位互換
    • 詳細はコチラ
  • Mediaスポンサー(お問い合わせください)
    • Webサイトにバナー(小)を掲載
    • 招待枠: 1名

お問い合わせ先

2012-07-10

Node.js のカンファレンス「東京Node学園祭 2012」を開催します

Node.js日本ユーザグループは、Node.js開発リーダーである Isaac Z. Schlueter氏を始めとする海外ゲストを招聘し、第2回目のカンファレンスとなる「東京Node学園祭 2012」を、下記のとおり開催いたします。

最新のNode.jsの動向、企業内でのリアルな導入例、初心者向けのセミナーからLT大会まで盛り沢山の内容を予定しております。エンジニア同士や講演者と交流できる時間も多く設けるつもりですので、是非この機会に交流を深めて頂ければと思います。

日時: 2012年11月18日(日) 10:00-17:30(予定) / 後夜祭 18:00-
会場: 法政大学 市ヶ谷キャンパス 外濠校舎
セッション: 2トラック並行で10セッション前後を予定
基調講演: Isaac Z. Schlueter氏(@izs)
海外ゲスト: Charlie Robbins氏(@indexzero)、Mikeal Rogers氏(@mikeal)、James Halliday氏(@substack)
参加費: 無料 / 後夜祭は実費
募集人数: 400名
主催: Node.js日本ユーザグループ
後援: 法政大学情報科学部
スポンサー: 別途公募いたします

参加者募集は、夏の終わりから秋口あたりに開始する予定です。今のうちから予定を空けておいてください!
セッション登壇者やスポンサーにつきましては、間もなく公募を開始いたしますので奮ってご応募ください。

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-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 で」こそフォローすべきスーパーエンジニアと言えるでしょう (筆者を除く).

2011-10-05

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



Jxck です。

少し前、以下のような記事がポストされたのを覚えてますでしょうか?

今すぐフォローすべきnode.js界のスーパーエンジニア

自分もこの記事にリストしていただいて、非常に光栄です。
しかし一方で、載った自分からしても、手放しに喜べない点があったのも事実でした。

それは、ここに上がっているのは日本人だけで、僕らが思う
本当のスーパーエンジニアの多くは、海の向こうで大活躍してるという点です。

また国内に絞ってみても決して外してはいけない、「あの人」が。。

自分としては、是非彼らの活躍にも注目してもらいたいと思っています。
そこで今日は Node.js のことを知りたい方がフォローすべき、
本当のスーパーエンジニア達を紹介したいと思います。
多くてもあれなので、10人に絞ってみます。


@ryah
Ryan は言わずとしれた Node.js の生みの親です。彼を抜きに語る事はできません。
現在は Joyent に在籍しフルタイムで Node.js の開発に従事しています。
Twitter での発言は少なめで、よく "favorite song" をポストしてたりします。
東京Node学園祭2011 に登壇のため 10月に初来日の予定です。
というか、もうフォローしてますよね?


@izs
Izaac は npm の作者でシリコンバレーのベテランプログラマです。
Ryan と同じく Joyent で働いています。
以前のアイコンの写真は少し暗そうなイメージがありましたが(最近変わった)、
実際は結構明るい感じです。
Unix 文化にも造詣が深く、Node.js のコアにもその精神を反映しています。
少しマイナーですが、slideというフローコントロールライブラリを見ると彼のセンスが伺えます。


@sh1mmer
Tom は Joyent のチーフエバンジェリストで、元は Yahoo のエンジニアです。
自転車が目印で、Joyent の中でも兄貴的な存在です。
Oreilly から出る Node.js 本 "Up and Running with Node.js" の著者でもあり、
イベントでも幅広い発表をしています。ベジタリアンです。


@rauchg
Guillermo はアルゼンチン出身で、 Socket.IO や mongoose の作者です。
@tjholowaychuk がいる LearnBoost の CTO でもあります。
今は mongoose は離れて Socket.IO に注力しているようです。
とても若くてイケメンです。
同じく学園祭登壇予定です。ちなみに、Socket.IO に興味があるなら、
彼と同じくコミッタである @3rdEden もフォローするといいでしょう。


@tjholowaychuk
TJ は、Express をはじめ Jade, Stylus, Cluster, Connect, Expresso, Should, Tobi などなど、
数多くのプロジェクトを驚異的な生産性でこなす本物のスーパーエンジニアです。
github で彼を追いかけると、そのコミットの速さに驚くことでしょう。
Node.js 界のエコシステムに大きく貢献していて、現在書籍も執筆中だそうです。
あまりカンファレンスなど表には出てこない人で、
コミュニティにも彼と会ったことがある人はほとんどいないそうです。
(今年の学祭も、残念ながら断られてしまいました。。)
彼もまたとても若く、家ではフェレットを飼っています。(この名前が Tobi の由来)


@indexzero
Charlie は Nodejitsu のエンジニアです。 Nodejitsu は、サービスを
 Node.js で運用する中で得た経験をもとに、forever, node-http-proxy, winston など、
ちょっと触る程度では必要ないけど、本気で取り組むと必ずたどり着く、
玄人向けモジュールを数多くリリースしています。
彼らはその中心を担うエンジニアで、実力者かつイケメンです。


@felixge
Felix は node-mysql などの開発者で、現在は Node.js のコアコミッタでもあります。
Felix's Node.js Guide には、Node.js のチュートリアルから、スタイルガイド、
上司の説得方法まで幅広く書かれているので、これから始める人は
ぜひ読んでみるといいでしょう。
彼が在籍する Transloadit というサービスは、 Node.js を活用した
成功例の一つと言えます。
背が高く気さくな青年です。彼もまたとても若いです。本当にみんな若い。。


@mikeal
Mikeal は NodeConf の主催者で Mozilla, CouchOne, Yammer と渡ってきた実力者です。
request という HTTP モジュールを公開するように HTTP 周りに非常に詳しく、
ML でも Node.js コアの通信周りにも鋭く切り込む場面がたまにあります。
@jedschmidt とは友人で、ラーメンが大好きな彼は、自分で作るために、
Jed に「かん水」を日本から送ってくれるように頼んだほどのラーメン好きですw


@substack
VM からロボットまで幅広い技術をもつオークランド在住のエンジニアです。
Web サイトの各ブラウザの見た目を確認できる browseling というスタートアップの
サービスを提供し、npm モジュールをブラウザで使えるようにする
  node-browserify などのモジュールを公開しています。
ロボットをはじめとするコミカルなイラストが特徴です。(http://substack.net/)


@koichik
忘れてはならないのが、日本人で初めて Node.js のコアコミッタになった koichik さんです。
もともとは Seasar 関連のコミッタもやっているので、
Java を使う人ならもしかしたら知っているかもしれません。
node-handlersocket も公開していて、日本語ドキュメントも本家のドキュメントが
更新されてから1日程度で訳を公開しています。
東京Node学園で発表された 『「非同期プログラミングの改善」のエッセンス』は、
非同期プログラミングがベースの Node.js でプログラムを書く上では必読です。


ということで 10 人紹介しました。
他にも優秀なエンジニアはたくさんいますので、この10人からたどって、
自分の興味のあるモジュールのコミッタなどをフォローしていくといいと思います。

2011-10-01

「東京Node学園祭2011」 開催いたします!

皆様、いかがお過ごしでしょうか。

来る 2011/10/29 に Node.js 日本ユーザグループによる
Node.js カンファレンス "東京Node学園祭2011" を開催いたします。

Node.jsの生みの親 Ryan Dahl 、 Socket.IOの作者 Guillermo Rauch がスピーカーとして登壇いたします。

詳しくは、東京Node 学園祭 公式サイトをご覧ください。
東京Node学園祭

東京Node学園祭 公式Twitterアカウントもございます。
フォローしていただくと最新情報をご確認いただけます。
東京Node学園祭 Twitterアカウント

Twitterでの公式ハッシュタグは #nodefest となります。

2011-09-26 追記
チケットについて2011-09-26より販売開始となりました! ご参加希望の方はチケットをご購入ください。
詳しくはチケットのご購入ページをご参照ください。

会場はYahoo! JAPAN様 11Fとなります。
詳しくは会場へのアクセスをご参照ください。

2011-10-01 追記
チケット販売は閉め切らせていただきました。
みなさんありがとうございました。

2010-12-26

Express と Expresso を使う際の注意点

12/26 現在 npm でリリースされている Express 1.0.0 と Expresso 0.7.0 を使う際の注意点です。

1つ目

コマンドラインで自動生成されるテストコードにバグがあります。

Express では、
$ mkdir foo
$ express foo
で、プロジェクトを自動生成できます。 /test に app.test.js というテストコードがあります。これは Expresso 用のテストコードですが、いまの Expresso では動きません。そこでテストコードを以下のように修正します。

修正その1

※ ちなみに このエクステンション を使うと gist の diff がとれます。便利すぎるのでおすすめです。

これでルートディレクトリから
$ expresso
を実行すると、テストが走ります。Github のコードは修正されているので、もうしばらく待っていたら解消すると思います。



2つ目

Expresso では -c でカバレッジを取ることができますが、 /lib 配下のコードにしか対応していません。そこで /lib をつくって app.js を移動します。

$ mkdir lib
$ mv app.js lib
外部ファイルのパスを修正します。


テストコードのパスも修正します。

修正その3

テストは expresso の引数でライブラリのパスを指定して実行します。

$ expresso -I lib -c

これでカバレッジも取れるようになりました。

最終的なソースコードはこうなっています。


以上、 Express と Expresso を使う際のちょっとした注意点でした。

Happy Noding!


2010-12-25

HTTP と WebSocket でセッションを共有する

こんにちは、 nodejs.jp@masahirohです。 JavaScript Advent Calendar の最終日です。クリスマスだけど空気を読まずに Node.js の地味な話をします。ごめんなさい。

さて、 Node.js では Socket.IO を使えば、 WebSocket を使ったアプリケーションを割と簡単に作れるわけですが、これを Web フレームワークと一緒に使う場合、どうやってセッションを共有したらいいんだろう?とふと思いました。ユーザ名とパスワードをメッセージにのせたらいいんですかね? いや、セッション ID をメッセージにのせればいいのかな? うーん・・と思いながら Github をうろうろしていたら SessionWebSocket というアプリケーションを見つけました。セッション管理機能を追加する方法が結構参考になったので、コードリーディングをします、の予定だったのですが、動きがおかしかったので、一部書き直しつつ、コードリーディングします。説明の都合上、元のコメントは残していません。


解説に使ったソースコードは ここ の ma-read ブランチにあります。


では、解説していきます。まず、おおまかに言うと、セッション管理の仕組みは次のようになっています。


  1. ユーザが最初にページを開いたときに、クライアントは XHR でセッションのトークンを要求します。
  2. サーバはそのトークンをキーとしてセッションオブジェクトを管理しています。クライアントからの要求に応えて、トークンを返します。
  3. トークンを受け取ったら、 WebSocket のコネクションを開いて、そのトークンを送信します。
  4. WebSocket サーバはトークンを受け取ったら、管理しているセッションの有効期限をチェックし、有効ならセキュアなセッションとみなします。

server.js

では、サーバ側のコードから見ていきます。

依存しているモジュールをインポートしています。インポートしているのは、 Connect, Socket.IO, SessionWebSocket です。
var connect = require("connect");
var io = require("socket.io");
var sws = require("../sws.js")();
まずは Connect で Web サーバをつくります。 Connect は Web アプリケーション用のミドルウェアフレームワークです。決められたインターフェースに従ってつくられたアプリケーションを pluggable なミドルウェアとして扱うことができます。

createServer の引数に渡しているのがミドルウェアです。
var server = connect.createServer(
HTTP のセッションを管理しています。
  connect.cookieDecoder(),
  connect.session(),
今回の主役のひとり。セッションのトークンを発行します。
  sws.http,
これは静的ファイルを扱います。
  connect.staticProvider(__dirname+"/static")
);
サーバをポート 8000 番で起動します。
server.listen(8000);
次に、 WebSocket のサーバを準備します。

さきほどの Web サーバが WebSocket を扱えるようにしてやります。
var socket = io.listen(server);
イベントハンドラを設定します。引数に渡している sws.ws がもうひとりの主役です。 WebSocket 側のセッションを管理しています。こんなふうにコールバックにコールバックを渡すあたりがたまらないですね。
socket.on('connection', sws.ws(function(client) {
認証済みの場合のイベントハンドラです。セッション ID を出力してみます。
  client.on("secure", function() {
    console.log("SECURE");
    console.log(client.session.req.sessionID);
  });
認証が済んでいない場合のイベントハンドラです。
  client.on("insecure", function() {
    console.log("INSECURE ACCESS");
  });
メッセージ受信時のイベントハンドラです。
  client.on("message", function(msg) {
    client.send(msg);
    console.log("MSG:"+msg);
  });
}));

sws.js

var util = require('util');
では、いよいよセッション管理のミドルウェアについて見ていきます。

関数を exports にセットしています。先ほどアプリケーション側で require したときに呼んでいました。引数からオプションを受け取るために関数にしていたわけですね。
module.exports = function verifier(options)
{
デフォルトの設定です。セッションの生存期間 (ttl = time to live) を設定しています。
  var defaults = {
    ttl: 30*1000 // 30 秒
  };
引数でもらったオプションを反映させています。
  for (var k in options) {
    defaults[k] = options[k];
  }
複数のセッションを扱うためのオブジェクトです。
  var session_jar = {};
この関数は、セッションのトークンを発行するミドルウェアと、 WebSocket 用のセッション管理の関数をプロパティにもつオブジェクトを返します。
  return {
先ほど createServer に渡していたミドルウェアです。 リクエストオブジェクト、レスポンスオブジェクト、next という関数を引数にとる、というのが決められたインターフェースです。
    http:function give_token(req, res, next) {
リクエストのヘッダを参照し、 'x-access-request-token' フィールドが 'simple' だったらトークンを生成します。
      if (req.headers["x-access-request-token"]) {
        if (req.headers["x-access-request-token"].toLowerCase()==="simple") {
          var token = Math.random();
ユニークな値をとれるまで繰り返します。
          while (session_jar[token]) {
            token = Math.random();
          }
トークンをキーとしてセッションデータと発行した日時を保存しています。 req.session は connect.session が生成したものです。
          var tmp = Date.now();
          session_jar[token] = {
            session: req.session,
            date: tmp,
            id: req.sessionID
          };
レスポンスを生成します。トークンと発行日時を JSON で返しています。
          res.writeHead(200);
          res.end('{"x-access-token": "'+token+';'+tmp+'"}');
          return;
        }
      }
'x-access-request-token' フィールドがリクエストのヘッダにない場合は、このミドルウェアはやることがないので、 next を呼んで次のミドルウェアに処理をまかせます。
      if (next) {
        next();
      }
    }
こちらは WebSocket のセッションを管理する関数です。
    , ws: function attach_client(cb) {

      return function route_client(client) {
トークンの有効性をチェックする関数を定義します。
        function verify(token) {
          var tmp = session_jar[token];
セッションの期限切れをチェックしています。認証されたら削除しているので、トークンは1回だけしか使わない仕様になっています。
          if (tmp && tmp.date > Date.now() - defaults.ttl) {
            var session = tmp;
            delete session_jar[token];
            return session;
          }
          return false;
        }
'message' に対するイベントハンドラを設定します。トークンをチェックしています。この関数を実行するのは最初にメッセージを受信したときだけです。
        client.once('message', function first_verify(msg) {
メッセージで渡されたトークンが有効な場合は、クライアントにセッションデータを設定して、'secure' イベントをクライアントに対して発行します。
          var session = verify(msg) || false;
          if (session) {
            client._session = session;
            client.session = session.session;
            client.emit("secure");
セッションが有効だったので、 client.on を元に戻して、退避しておいた 'message' に対するイベントハンドラをバインドします。退避する処理は下の方にでてきます。
            client.on = oldon;
            for (var i = 0, l = onmsgs.length; i < l; i++) {
              client.on('message', onmsgs[i]);
            }
          }
セッションデータがないので 'insecure' イベントをクライアントに対して発行します。
          else {
            client.emit("insecure");
          }
        });
'message' イベントに対するイベントハンドラは、セッションが有効かどうかのチェックが済んだあとから実行されるようにしたいので、 client.on を 'message' イベントのハンドラだけ退避するように書き換えます。
        var onmsgs = [];
        var oldon = client.on;
        client.on = function(name, fn) {
          if (name === "message") onmsgs[onmsgs.length] = fn;
          else oldon.apply(this, arguments);
        };
        
呼び出し元にクライアントを渡します。
        cb(client);
      };
    }
  };
};

client.js

次にクライアント側を見ていきます。

SessionWebSocket で、トークンのやりとりをしてから、 'message' に対するイベントハンドラをバインドします。
SessionWebSocket(function(socket){
 socket.on('message',function(msg){
  console.log("SWS:",msg);
  });
セッションが確立した場合、このメッセージは受信されます。
  setInterval(function() {
    socket.send('Succeed!');
  }, 1000);
});
セキュアでないコネクションを示すための例です。こちらで送信したメッセージは弾かれます。
var socket = new io.Socket()
socket.connect();
socket.send("OH NOES");

sws.js

次に クライアントサイドのモジュールのコードです。トークンを取得して、返ってきたらコネクションを張り直します。
function SessionWebSocket(cb) {
  var xhr = new XMLHttpRequest()
  xhr.open("GET","/?no-cache="+(new Date()+0));
トークンを取得するためのヘッダを設定します。
  xhr.setRequestHeader("x-access-request-token","simple");
レスポンスに対するコールバックを設定します。
  xhr.onreadystatechange = function xhrverify() {
受信完了
    if (xhr.readyState === 4) {
      var tmp;
      try {
トークンが返ってきていたら、新規に WebSocket の接続を開始します。
        if (tmp = JSON.parse(xhr.responseText)["x-access-token"]) {
          var socket = new io.Socket();
          cb(socket);
          socket.connect();
取得したトークンを送っています
          socket.send(tmp.split(";")[0]);
        }
      }
      catch(e) {
        throw new Error("XMLHttpResponse had non-json response, possible cache issue?")
      }
    }
  };
リクエストを送信します。
  xhr.send();
}




以上でおしまいです。個人的には Connect のミドルウェアとしてセッション管理を実装するあたりや、イベントハンドラを一旦避けるあたりの処理が面白かったです。改善の余地がちょこちょこあるので、手を入れていこうと思います。


* このドキュメントは docco をつかってコードから生成しました。
  • HOME
  • ABOUT
このページの先頭へ