- 清水俊博(@meso)
- 株式会社ドワンゴ 技術コミュニケーション室
- Node.js 日本ユーザグループ
-
Webブラウザ外で動作する、ノンブロッキングI/O環境上に構築されたJavaScriptの実行環境(プラットフォーム)
-
いわゆる"サーバサイドJavaScript"の1つ
-
Node.js 以外にも従来からいくつも存在
- Netscape Enterprise Server, IIS+JScript, Helma
- Aptana Jaxer, Narwhal, RingoJS
-
流行らなかった
- JavaScriptがしっかりしたプログラミング言語として認められてなかった時代
- 「別にサーバサイドまでJavaScript使いたいと思わないんだけど」で玉砕
-
Node.jsの目的は「サーバサイドでJavaScriptを使いたい」ではない
-
Node.jsの作者Ryan Dahlの目指したもの
- Node's goal is to provide an easy way to build scalable network programs.
- Nodeの目的は、スケーラブルなネットワークプログラムを作成する簡単な方法を提供することです
-
この目的を達成するには、解決しなければいけない問題があった
- C10K問題
- ハードウェアの性能に関わらず、同時接続できるクライアント数に限界がきてしまう問題
- リアルタイムWebの普及で現実になってきた
- 原因は複合的だが、主な原因の1つはスレッド数の増大
- メモリ割り当て
- 1スレッド増えるとOSにより2~4M割り当てられる
- コンテキストスイッチ
- スレッドが増えると、処理を走らせるスレッドを切り替えるのにもコストがかかる
- メモリ割り当て
- ハードウェアの性能に関わらず、同時接続できるクライアント数に限界がきてしまう問題
-
スレッドモデル
-
1リクエストに対して1スレッド
- レスポンスを返すとスレッドは終了
-
たとえ分間1万アクセスだとしても、スレッドが同時に1万本必要にはなるようなことはない
- レスポンスを返すのに1分かかるような特殊なWebアプリケーションでもない限り
Software Design 2011年9月号
-
Comet
- サーバがレスポンスをすぐに返さずに保持し、必要なデータが用意できたら返す仕組み
-
WebSocket
- サーバとブラウザ間でSocketを張りっぱなしにして、いつでも通信ができる
-
これらによって、分間1万アクセスならスレッドが同時に1万本必要になってしまう
-
イベントループモデル
-
ノンブロッキングI/O
-
1つのスレッドがイベントの発生を待機
-
イベントが発生したらそのイベントに即した処理を行う
-
重い処理を行う際には「その処理が終わったというイベントが発生したら行う処理」を登録し、次のイベントの発生を待つ
- 重い処理の結果が返ってくるのをその場で待ち続けはしない
-
シングルスレッドでも多数の同時リクエストをさばくことが出来る
Software Design 2011年9月号
http://blog.webfaction.com/2008/12/a-little-holiday-present-10000-reqssec-with-nginx-2/
http://blog.webfaction.com/2008/12/a-little-holiday-present-10000-reqssec-with-nginx-2/
-
1箇所でも重い処理を持つコードがあれば、シングルスレッドゆえに全体の性能が低下する
-
プログラムにとっての重い処理
= CPUがフルに働けずに待ち時間が発生する処理
= ディスクやネットワークのI/O待ち
種別 | サイクル | メートル換算 |
---|---|---|
L1キャッシュ | 3 | 3m |
L2キャッシュ | 14 | 14m |
メモリ | 250 | 250m |
ディスク | 41,000,000 | 地球1週 |
ネットワーク | 240,000,000 | 地球6週 |
- プログラマが見極めるんじゃなくて、強制的にI/Oを非同期にしてしまおう
- libuv(libev, libeio)によって実現
- I/O待ちによってブロックされることがないため性能が低下しない
-
ブロッキングI/O
var user = db.exec('select * from users where id=123'); // 結果をここで待つ display(user.name); ```
-
ノンブロッキングI/O
db.exec('select * from users where id=123', function(user) { // 結果を受け取ったらここが呼ばれる display(user.name); }); // 結果を待たずにここにくる ```
- このようなプラットフォームをどの言語向けに提供すべきか
-
シングルスレッドモデルである
-
イベントループの仕組みが備わっている
-
標準入出力の仕様がない
= 既存のI/Oライブラリが存在しない
= 全てのI/Oがノンブロッキングな世界を0から作り上げられる環境
-
cf. Twisted, AnyEvent, EventMachine
- ブラウザ戦争のおかげで高速なV8エンジン
- ユーザベースが大きい
- 新たな言語を覚えなくてよい
- 開発環境やツールが整備されている
- リアルタイムWebアプリケーション, ネットワーク・サーバ
- チャット, ゲーム, コラボレーションツール, Streaming, etc...
- クローラー
- 大量のI/Oウエイトが発生するがその時間を無駄にしない
- jQueryなどのDOM操作系のJSライブラリが使えるのでスクレイピングが楽ちん
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
var net = require('net');
var server = net.createServer(function (socket) {
socket.write('Echo server\r\n');
socket.pipe(socket);
});
server.listen(1337, '127.0.0.1');
- Ameba ピグライフ
- Mobage NgCore SDK
- GitHub, Yammer, LearnBoost, Transloadit
- http://bombermine.com/
- http://jp.techcrunch.com/2011/09/10/20110909node-js-knockout-2011-winners-revealed/
- node-webkitを使ったGUIアプリケーション
- Grunt, CoffeeScriptコンパイラ, ChaiなどのJSテストツール
- このプレゼンテーション