2012年2月9日木曜日

Node.js on Herokuのベンチマーク

Node.js on Herokuの開発環境がとりあえずできてみたので、ちょっとベンチマークをとってみた。といっても、相手はHello Worldを返すだけの最小Webアプリなので、その辺は割り引いて考えてください。

サーバ環境:Herokuの公開用サーバのWeb Dynos(無料枠なので1Dynos)
アプリ環境:Web DynosのCedarスタック上のNode.jsアプリ(Hello Worldを返すだけ)
クライアント環境:MacOSX(Lion)上の標準Java上のJmeter

最初、MacOSXに標準で同梱されているApache Bench(abコマンド:こんなのも同梱されてるって、どんだけ開発者寄りなんだOSX!)で、さくっと感覚だけ掴んでみるべ、と思ったんだけど、並列リクエスト数4(-c 4)あたりからなんだか挙動がおかしなことになってきて、Socketエラーが出てしまう。

これは明らかにHerokuの問題じゃなさそうだな、、、と思ってググってみると、標準のabはイケてないので、ソースからビルドし直した、なんて記事があったりしてガックリ。

ソースから入れ直すのもいいけど、標準abと入れ直したabが混在するのも構成管理上気持ち悪いし、いっその事Jmeterで真剣にやるか、ってな感じに決着がついた(自分内で)。

で、結論的には、

350req/sec(Keep-Alive無効時)
500req/sec(Keep-Alive有効時)

あたりのスループットまで到達した。

ここまでくるとそれ以上に行くためのネックがサーバなのかクライアントなのかネットワークなのかは置いておいても、十分すぎるほどの性能。

前述の通り、アプリは何も処理してないに等しいのは確かだけど、1Dynos(=1プロセス<1物理CPUcore、でいいのかな)だけで、350ものコネクション(/sec)の切った張ったをできるだけでも超優秀と言ってもいいんじゃないだろうか。

いじりがいがあるな〜。

(尚、レスポンスタイムはおおむね400ms前後で、こっちはちょっと残念な感じ。サーバが米国だから仕方ない面もあるけど、400msあると人は引っかかりを感じるだろうから、アプリっぽいWebアプリを、サクサク動かすにはちょっとつらいか)

2012年2月7日火曜日

HerokuでNode.jsを始めてみる

Heroku公式サイトのここを見る。おしまい。

・・・いや、ほんとにそうだから。
簡単すぎて半笑いでやりました。

Windowsだとちと大変かも知れない。
Mac(Lion)だと得体の知れないラクさ加減。
Node.jsをローカルにインストールするところで若干戸惑うが、Node.jsとnvmを初めてインストールするときのハマりポイントと対策を参考にさせてもらいました。
(尚、ここに書いてあるのはNode.js v0.4.0時点のもので、自分はv0.4.7で試したところ、wgetは不要でいけました。nvmコマンドの出力形式も多少違う)

あとは、Xcodeさえ入ってれば、Lionにはgitも入ってるし何にも悩むことがない。

学んだこと・・・

  • nvmコマンドって、Node.jsのパッケージマネージャなんですけど、Node.jsそのものまでインストールできるのにビビる。Node.jsが存在しない状態で実行できる。まじか。。。
  • MacOSXの開発者フレンドリーな環境にビビる。gitまで入ってんのか〜。。。
  • Herokuって、多言語に対応してるんだけど、どこで「僕はNode.jsを使うの!」って指定するのかな、っと疑問だった(何しろHerokuといえばRoR、の記事ばっかで・・・)が、Procfileというファイルで指定すれば良いらしい。悩まないでプログラミング界の格言(?)「考えるな、真似ろ」に従っておけば良かったわ。
  • gitでデプロイするのは分かってしまえば(GAEのappcfgとの比較で言うと)バージョン管理も直感的だし(つうか、そもそもgitはバージョン管理するためのプロダクトなのだが・・・)好きかも。ただ、いかんせんgitはちゃんと触ったことがないので、慣れるまでは我慢か。
  • Windowsで環境を作るのは正直おっくう。
さあ、バリバリ遊ぶぞ〜。

2012年2月1日水曜日

WebSocketとかChannelとか

GAEのChannelは、無料枠では1日100オープンまでだし、HerokuのWebSocket(Pusher)は無料枠で20コネクションまでだし、リアルタイム性の高いPush通信は、コストが高くついて困るなあなんて話を過去のエントリでしたわけですが、

考えてみると、Push It!は、通信対戦アクションゲームのようなギチギチのリアルタイム性を求めているわけでなく、数秒程度の遅延で付箋が更新されれば良くって、だったらChannelやWebSocketである必要なくね?と思い返した。

ただ、短周期のポーリングは避けたいね、クライアントにもサーバにもネットワークにも負荷だし、というのがそもそもChannelやWebSocketを使おうとしたそもそもの理由。

ってことは、Long Pollingでいいんじゃね?という気がした。

GAE/Python2.5だと、CPUすかすかでも1リクエストが1インスタンスを占有するから現実的ではないのだが、GAE/Python2.7(か、Java)だったらマルチスレッド対応なので、CPUすかすかなら対応できるかもしれない。

ただ、GAE/P(多分Jもだが)、リクエスト処理中に外部からのイベントを受け付けられる仕組みにはなってないので、更新があったかどうか、内部では短周期でポーリング(Datastoreなりmemcacheなりに対して)してあげないといけない。これがネック。

HerokuだとNode.jsが使えるので、外部からのイベントが来るまでリクエスト処理は放置しておけるんじゃないか?だとしたら、Long Pollingがかなりラクかつ低負荷で実施できそうな気もする。
どうなんだろ。試してみたい。