「東京Node学園 1時限目」が無事に終わりました

開催にあたってご尽力頂いた各位にお礼申し上げます。

資料等は http://blog.nodejs.jp/2011/03/node-1_25.html にまとめていますので是非ご覧ください。
ただし、なんか最新のChromeで見るとところどころ文字化けしてるように見える……。

イベント中にもお伝えしましたが、Nodeに対する興味がより高い方を優先して参加していただけるよう今後のイベントはまずNode.js日本ユーザグループMLに流し、その後Twitter等でオープンにするという形にします。

ですので、今後もNode.js日本ユーザグループ主催のイベントに参加したいという方は、是非MLに参加してください。

Amazon EC2 MicroインスタンスのAmazon LinuxにNodeをインストールした

ついに東京にやってきたので。

AMI(Amazon Machine Image)は基本となるBasic 64-bit Amazon Linux AMI 2011.11.1 Beta (AMI Id: ami-9008a391)を選びました。UbuntuとかSUSEとかもあるから好きなの選べばいいんだけど、Ubuntuなら既にインストールの情報多いからあえて違うので。

とりあえず、SSHでログインできるようになってからの作業ログ。

# 時計をJSTに
$ sudo cp /usr/share/zoneinfo/Japan /etc/localtime
# 必要なパッケージのインストール
$ sudo yum install git gcc-c++ openssl-devel
# nvmの準備
$ git clone git://github.com/creationix/nvm.git ~/.nvm
$ echo . ~/.nvm/nvm.sh >> ~/.bashrc
$ . ~/.bashrc
# nvmを使ってNodeをインストール
$ nvm install v0.4.2

これでNode v0.4.2と最新のnpmがインストールされます。あとは、

$ nvm use v0.4.2

とすれば node コマンドや npm コマンドにパスが通るので使えるようになります。

makeに時間はかかったけど、とりあえずプロセスが殺されるようなことはありませんでした。

Node.jsの勉強会「東京Node学園 1時限目」を開催いたします

Node.js日本ユーザグループとして定期的に勉強会を行っていこうという話がありまして、その第一回として3月24日に「東京Node学園 1時限目」を開催いたします。開場は、リクルート メディアテクノロジーラボさんをお借りします。会場提供を快諾していただきありがとうございます。

ATNDは http://atnd.org/events/13529 ですが、このエントリを書いている時点で既にキャンセル待ちになってしまっています。

し・か・し!LT発表者はキャンセル待ちでも参加できますので、キャンセル待ちだけどどうしても参加したい方は是非LTするよ!と表明してください。お待ちしております!

jsdo.itで動くWebSocketのチャットをはてダに貼ってみる

jsdo.itのブログパーツが貼れるらしいので試しに。

WebSocket(Socket.IO)を使ったチャットサンプル - jsdo.it - share JavaScript, HTML5 and CSS

サーバサイドはもちろんNodeです。
リアルタイムWebハッカソンでハンズオンしてきました - 自分の感受性くらいで作成したチャットとサーバは共同なので、http://riajyu.mesolabs.com/でも同じログが表示されるのが確認出来ると思います。

認証等は皆無なのでTwitter IDに適当に他人のIDを入力すると簡単に成りすましができます。あと、アイコンの表示にはid:dankogaiTwitterアイコンAPIを勝手に使わせてもらっています。

サーバサイドの実装も含めてソースはGithubで公開していますが、Nodeがまだv0.2.xの時代に作ったものなのでちょっと書き方が古いとこもあります(とはいえ最新のv0.4.1でもそのままで動いてますが)。

ATNDのリマインダーをNodeで書いてみた

Node.jsの正式名称はNodeということらしいので、これからはNodeと表記しますね。

今日、「Node.jsの飲み会」というイベントをやるんですが、信頼のドタキャン率を誇るATNDで募集していたので、ATNDのアカウントをTwitterとひもづけてる人に対してTwitter経由でリマインダーを送るプログラムをNodeで書いてみました。

var request = require('request'),
    qs = require('querystring'),
    OAuth = require('oauth').OAuth,
    settings = require('./settings'),
    oauth = new OAuth(
      'https://api.twitter.com/oauth/request_token',
      'https://api.twitter.com/oauth/access_token',
      settings.oauth.consumer_key,
      settings.oauth.consumer_secret,
      '1.0a',
      null,
      'HMAC-SHA1'
    );

function getUsers(eventId, callback) {
  var params = {
    format: 'json',
    event_id: eventId
  }
  var url = 'http://api.atnd.org/events/users/?' + qs.stringify(params);

  request({uri: url}, function(err, res, body) {
    if (err) throw err;
    if (res.statusCode !== 200) throw new Error('ATND API returns NG');
    
    var event = JSON.parse(body).events[0];
    event.users.forEach(function(element, index, array) {
      callback(event, element);
    });
  });
}

function update(message) {
  oauth.post(
    'http://api.twitter.com/1/statuses/update.json',
    settings.oauth.access_token,
    settings.oauth.access_token_secret,
    { status: message },
    function(err, data) {
      err && console.log(err);
    }
  );
}

getUsers(13366, function(event, user) {
  if (user.status === 1 && user.twitter_id) {
    update('@' + user.twitter_id + ' 今日は「' + event.title + '」の日です!あなたは参加人数にカウントされておりますので、もし参加できない場合は今すぐキャンセルをお願いします。お会いできるのを楽しみにしています!' + event.event_url);
  }
});

これをapp.jsという名前で保存します。同じディレクトリにsettings.jsという名前で

module.exports.oauth = {
  consumer_key:         'your consumer key here',
  consumer_secret:      'your consumer secret here',
  access_token:         'your access token here',
  access_token_secret:  'your access token secret here'
}

という内容のファイル(それぞれのキーはTwitterAPIのページで取得してね)を作成して、あとは

$ node app.js

で、リマインダーをスパムのようにつぶやきます。

Github: https://github.com/meso/ATND-Reminder
もし要望があれば、これにWebインタフェースつけてこういったリマインダーを送るサービスでも作ろうかしら。

Node.jsについてのよくある誤解

Node.jsは普及しそうに無い: ニュースの社会科学的な裏側

http://anlyznews.blogspot.com/2011/02/nodejs.html

という記事があったので、もしかしたらいい感じにNode.jsについてのよくある誤解がここに網羅されてるんじゃないかと思ってエントリを書きます。決して顔真っ赤にして反論してるわけじゃないよ!

で、まず

理由は簡単で、Googleがリリースしたアプリケーション・サーバーであるnode.jsが、JavaScriptとその実行エンジンを基本とした構成となっており、その性能が高いからだ。

とありますが、Node.jsはGoogle製ではありません。Node.jsがベースとしているJavaScriptのV8エンジンはGoogle製(のオープンソース)ですが、Node.js自身はJoyentという会社のサポートによって作られています。メインコミッタのRyan DahlもJoyentの社員です。
修正されてました!

あとは、

9. node.jsの問題点
高負荷時のパフォーマンスが優れているのは確かのようだが、現状では次のような欠点もある。万能薬的な使い方は出来ないようだ。

この項目について書けばいいと思うので各指摘点について書いていきます。っていうか、どのような言語であれどのようなフレームワークであれ得手不得手(もしくは適材適所)というものがあるので、万能薬は存在しないというのは一般的な共通認識ということでいいんじゃないのかな。Node.jsの開発者でNode.jsは万能だと言ってる人は誰一人みたことがないですし。

1. イベントループ・モデルで処理を直列化しているので、あるリクエストの処理に時間がかかる場合、他の全てのリクエストをブロックする可能性がある。

まず、この処理というのがI/Oを伴うものだと仮定すると、Node.jsはI/Oを非同期で行うためブロックは発生しません。他の非同期フレームワークであるTwisted(Python)やEventMachine(Ruby)などでは、組み合わせて使用するその言語のライブラリ次第でブロックが発生してしまうことがありますが、Node.jsは非同期であることが前提の環境なのでライブラリで同期I/Oが使われていてそれを同期呼び出しするようなケースはほぼありません*1
I/Oを伴わない部分だとすると、そのように時間のかかる処理(CPUインテンシブな処理)には向かないと言えます。ただ、一般的なWebアプリケーションであればI/O処理よりもCPU処理に時間のかかるケースというのはほとんどないのではないでしょうか。CPUがL1/L2キャッシュやRAMのみを用いて処理している場合とHDDやネットワークを用いる場合との差は、以下のエントリに端的に表現されています。

このブロックしてしまう処理というのはI/Oに端的に表れていて、たとえばCPUのL1キャッシュだと3サイクル、L2で14、RAMだと250で済むんだけど、それがDISKになると41,000,000サイクルかかって、ネットワークならさらに240,000,000サイクルもかかってしまうんだ。これがどのくらいすごいのかというと、サイクルをメートル換算してみるとわかりやすい。RAMでも250メートルでまだ目の届く範囲なんだけど、DISKになった瞬間、地球一周分、ネットワークだとさらに地球6周分!!!このコストの比はやっぱりトンデモナイんだよね。

http://d.hatena.ne.jp/badatmath/20101020/1287587240

あとはまあ、子プロセス作ってCPUインテンシブな処理はそっちにさせるってのも手ですね。

2. イベントループ・モデルで平行処理を行わないため、複数コアを持つCPU/MPU、複数のCPUを使うSMPでパフォーマンスの上昇が、JavaScriptのコード部分は期待できない。

これに関してもそういう理解をしている人は多いと思いますし、実際にNode.jsを1プロセスだけ立ち上げてる場合ではその通りです。しかし、Node.jsには複数の子プロセスを起動してそれらに処理を分散させるための様々なツール(ライブラリ)が既に存在し、使用実績もあります。例えば、fugue, Spark2, clusterなどです。これらを使えばコアの数だけプロセスを立ち上げ、リクエストをそのプロセスにロードバランスするみたいなことが簡単にできます。セッションの共有とかめんどいんじゃないかって思われるかもしれませんが、ExpressのようなConnectベースのWebアプリケーションであれば、connect-redisを使うなどすれば2行追加するだけでセッションの共有ができるようになります。

3. JavaScriptプログラミング言語としての限界が影響する。つまり、オブジェクト指向が不完全であること、動的型付けでJavaC#に対して速度面に限界があること等が、大規模で複雑なアプリケーションには影響を及ぼす可能性がある。

オブジェクト指向が不完全というあたりはちょっとよく分かりませんね。動的型付けで速度面に限界があることが大規模で複雑なアプリケーションに影響を及ぼすというのもよくわかりません。
どちらかというと、JavaScriptのプロトタイプベースのオブジェクト指向が、JavaC#などのクラスベースのオブジェクト指向しかやってこなかった人にとって慣れるのに時間がかかるとか、そういった問題はあるかとおもいます。また、動的型付けなのでIDEの支援が受けにくいとか多人数による開発であればきちんとルールを決めておかないと混乱を巻き起こす可能性があるとかそういったことはあるでしょう。ただ、前者についてはJavaScriptに慣れてる開発者も多いでしょうし、後者については他の動的言語でも大規模開発の実績があるのだから乗り越えられる障壁なんだと思っています。

4. あるページのJavaScriptの文法エラーが、サーバーの停止を引き起こす。簡単なプログラム・ミスが、アプリケーションの非クリティカルな部分に発生したとしても、システム全体がダウンする結果となる。

これはひどい誤解で、クライアント側の(HTMLから呼ばれる)JavaScriptが間違っていたからといって、サーバ側のNode.jsのプロセスが止まるなんてことはありません。それとも僕が誤読してるのかな?

追記:誤読してたっぽい。あるページの処理を行うサーバ側のJavaScriptでエラーが発生した場合のことだったみたいです。これも下のコメントに書かれているとおり、適切なエラー処理を行っていればNode.jsプロセス全体がダウンするなんてことはありません。

5. 非同期化によるパフォーマンス向上がイベントループ・モデルに依存するため、イベントを受けるコールバック関数が多くなり(単純なファイル操作でも3回コールバックが発生する)、ソースコードの見通しが悪くなる。

これもよくある指摘なんですが、様々な対処方があります。JavaScript自体に関しても、Future(Promise)を使ったパターンやDeferredを使ったパターンなどのライブラリも充実していますし、Node.jsについてもasync.jsなどの使い勝手のいいライブラリが数多く存在します(ちょっと前のエントリだけどhttp://d.hatena.ne.jp/koichik/20100926#1285502400参照)。

6. 利用可能ライブラリが限定的であり、開発支援ツールが無い。Apacheモジュールも種類や用途が多いし、JavaPHPにも覚えきれないほどのフレームワーク製品群とライブラリがある。これらに依存しない用途にしか、現状では利用できない。

利用可能なライブラリは確かに他言語に比べるとまだまだ少ないかもしれませんが、僕の個人的な感想では現状でもあまり不満はありません。また、既存のJavaScriptのライブラリ(例えばjQueryやYahoo!UIなど)は簡単にNode.jsから使うことができます。開発支援ツールという意味では、JavaScriptが使えるIDEやエディタなら大抵普通にコードは書けますし、Node Inspectorを使えばGUI環境でデバッグすることも可能です。ちなみにCloud9というNode.js製のIDEも存在し、これはローカルにインストールせずにホスティング環境で使うこともできます。
JavaPHPの誕生後1年でどれぐらいのライブラリやフレームワークが揃っていたかは知りませんが、生まれたての環境としては十分じゃないかなと思っています。ってか、欲しいのがあれば作ればいいだけだし、逆に言うと作って名を挙げるチャンスがあるとも言えますね。

終わりに

で、まあ上に書いたことは全部今書いてる本にもっと詳しく解説されています。というわけで出版されたら買ってね!という宣伝エントリでした。

*1:100%ではありませんが

JoyentとNodesterとDuostackに同一のnode.jsアプリをdeployしてみた

それぞれのホスティングサービスについての詳細は、前の記事を参照してもらうとして、比較するには実際に触ってもらうのがいいよねってことで以前Node.js Knockoutのときに作ったタイピングアプリを3つのサービスで動かしてみました。

このアプリは、WebアプリケーションフレームワークとしてExpress, テンプレートエンジンとしてjade, CSSフレームワークとしてless, WebSocketライブラリとしてSocket.ioを使ってます。

で、Socket.ioはWebSocketが使えないブラウザだったり環境だったりすると自動的にFlash SocketやXHR-Pollingやらに切り替えてくれるんだけど、

  1. Joyentは問題なくWebSocketが使えててスピードも申し分ない
  2. Nodesterは何も制約がないはずなのにWebSocketが使えずにXHR-Pollingになっている。ってか前はできたのに今はなぜかトップからゲーム画面に行けない
  3. DuostackはWebSocketとFlash Socketが使えないという制約があるので、プログラム上でそれを使わないようにしている。XHR-Pollingの速度は遅いけどNodesterに比べるとゲームが出来る分まだまし

といった結果になりました。以下がその実際のアプリのURLなので自由に触ってみてください。但し何時まで動作してるかは保証しかねます。

Joyent Node SmartMachine (http://no.de/)

http://jp.no.de/typing

Duostack (http://duostack.com/)

http://typing.duostack.net/

(追記: ついでにさくらVPSにもdeployしてみました) http://typing.mesolabs.com/

3サービスともにβ期間中なので登録にはクーポンが必要ですが、Joyentとその他では微妙に異なります。

  • Joyentはアカウントの登録は即時に可能ですが、アプリケーション(サブドメイン)ごとにクーポンの請求が必要になります。そして現在は1アカウントにつき1つのサブドメインに限定されています。
  • NodesterとDuostackはアカウントの登録にクーポンが必要で、アカウントさえ登録できればアプリケーション(サブドメイン)はいくつでも好きに登録できます。