明日も楽をするために

めんどくさがりなITエンジニアが書くメモ帳

Apache+nodejs+socket.ioを使ったリアルタイムWeb

普段のサーバーはApacheを使っているのですが、少し前にnodejsというサーバーからクライアントまでJavaScriptで書ける物がリリースされました。

nodejsはV8エンジンというGoogleChromeで使われている高速なエンジンを使用していたり、またApacheのC10K問題を解決しようとするものでした。

メリットも多いながらデメリットもそこそこあり、デプロイ時に再起動しないと新しいリソースが反映されなかったり(現在は解決してるのかな?)、イベント駆動ループ型なので、どこかでエラーが発生すると止まったり、またシングルスレッドで動くので最近主流のマルチコアCPUとは相性が悪かったりするんですが、デメリットを理解して使えれば色々と面白いです。

以下のBlog記事がとても面白かったです。実際のGreeの導入事例や、アメリカチェーンのスーパーマーケットWalmartブラックフライデー時の高負荷時にもサーバーが落ちずに耐えきった話など。

GREEが悩むNode.jsの問題を考えるヒント - ぼちぼち日記

隠れていたNode.jsの4バイトメモリリーク、Walmart問題の解決 - ぼちぼち日記

少しタイトルと話がそれましたが、そのnodejsはhtml5のsocket.ioの実装もとても簡単にできます。これが出来るとリアルタイムWeb(情報の更新をリアルタイムに反映し共有する概念やその仕組み)が使えます。

要するに、いままではブラウザ画面を更新したり、画面遷移をしたりと、クライアント(ブラウザ)側からアクションを起こさないと画面が切り替わりませんでしたが、これを使うとサーバーから好きなタイミングでクライアント(ブラウザ)に情報を送信できます。例えばチャットや、簡単なオンラインゲームなんかも作れたりします。

これ自体はnodejsだけでも出来るのですが、今回は裏の通信部分だけをnodejsで実装します。
以下がサンプルソースです。Apacheは80ポートで使用しているので、nodejsは今回は8080ポートを使用した想定です。

サーバー側

var io = require('socket.io').listen(8080);
io.sockets.on('connection', function (socket) {
    socket.emit('connected', 'connected');
/*
    socket.emit('news', { hello: 'world' });
    socket.on('my other event', function (data) {
        console.log(data);
    });
*/
    // クライアントが切断したときの処理
    socket.on('disconnect', function() {});
});

クライアント側

<html>
<head>
<meta charset="utf-8">
<script src="http://foo.co.jp:8080/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://foo.co.jp:8080');
/*
socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
});
*/
socket.on('connected', function (data) {
    console.log(data);
});
socket.on('disconnect', function (data) {
    //console.log(data);
    socket.disconnect();
});
</script>
</head>
<body>
HelloWorld
</body>
</html>

これで最低限の接続と切断が行えます。送信したいときはemitで受け取りはonで使用できます。

これを使って何か作ってみたいところです。

追記
Firefoxや、Thunderbirdを作ったMozillaが公開しているサンプル↓
nodejsとsocket.ioを使ってますbrowserquest.mozilla.org