リアルタイムWebを極める

第6回node.js、SignalRとクラウド、まとめ

これまで5回にわたってnode.jsとSignalRについて説明をしてきましたが、この両者は思った以上に似ている技術だと感じていただけたのではないかと思います。

連載の最後となる今回は、node.jsとSignalRのそれぞれを実際にクラウドで運用するにあたって、避けることができないスケールアウトについて説明を行って、それぞれの特徴と違いをまとめたいと思います。

まずはスケールアウトを行うにあたって必要となるRedisの説明を行っておきます。RedisとはオープンソースのKVS(Key-Value Store)なのですが、他のKVSにない特徴としてPub/Sub型のメッセージングが実装されていることが挙げられます。

 Redisは最近、非常に人気があるKVSの1つとなっている
図 Redisは最近、非常に人気があるKVSの1つとなっている

簡単に説明するとRedisを経由して複数のサーバ間でのメッセージのプッシュ通信が出来る機能です。この機能をnode.jsやSignalRでは使うことで、スケールアウトに対応しています。

node.jsとクラウド

socket.ioは接続されているクライアントの情報を、デフォルトではメモリ上に保持していますが、この情報をRedis上に保存することで、複数のサーバからでも参照することができるようになるわけです。

あらかじめsocket.ioにはRedisStoreという接続されているクライアントの情報をRedisに保存するためのモジュールが用意されているので、あとはRedisサーバだけを用意すれば簡単に試すことができます。

リスト socket.ioとRedisを使ってスケールアウトに対応した設定を行う
// socket.io
 
var io = require("socket.io").listen(app);
 
var port = 6379;
var host = "***.cloudapp.net";
 
var RedisStore = require("socket.io/lib/stores/redis"),
    redis = require("socket.io/node_modules/redis"),
    pub = redis.createClient(port, host),
    sub = redis.createClient(port, host),
    client = redis.createClient(port, host);
 
io.configure(function () {
    io.set("transports", ["xhr-polling"]);
    io.set("polling duration", 100);
    io.set("store", new RedisStore({
        redisPub: pub,
        redisSub: sub,
        redisClient: client
    }));
});
 
io.sockets.on("connection", function (socket) {
    socket.on("sendMessage", function (text) {
        io.sockets.emit("receiveMessage", { message: text, time: new Date().toLocaleTimeString() });
    });
});

第3回でWindows Azure Webサイトに作成したアプリケーションに関しても、Redisを使うことで複数のインスタンス上で動作させることが可能です。

socket.ioではRedisStoreを使うことで、既存のソースコードを殆ど変更することなく対応できました。

SignalRとクラウド

SignalRでもスケールアウトさせる際にsocket.ioと同様にRedisが使えますが、それ以外にもWindows Azureサービスバスを使ってスケールアウトが可能になっています。

RedisやWindows Azureサービスバスを使ってスケールアウトをさせるためには、以下のプラグインが必要になります。

  • Microsoft.AspNet.SignalR.Redis
  • Microsoft.AspNet.SignalR.ServiceBus

これらのプラグインはNuGetで公開されていますが、まだベータ版となっていてメモリリークなどの問題が残っているので、実際にサービスで使用するには正式版がリリースされるのを待つのが良いでしょう。

利用方法は非常に簡単で、NuGetからプラグインをインストールした後にGlobal.asax.csファイルに以下のような記述を追加するだけです。

リスト SignalRではRedisとWindows Azureサービスバスの両方が利用可能
public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        RouteTable.Routes.MapHubs();

        // Redis を使う場合
        GlobalHost.DependencyResolver.UseRedis("***.cloudapp.net", 6379, "", new[] { "SignalR.Key" });

        // Windows Azure サービスバスを使う場合
        var connectionString = "sb://...";

        GlobalHost.DependencyResolver.UseWindowsAzureServiceBus(connectionString, 2);
    }
}

同様に第5回で作成したアプリケーションをこのように修正することで、複数インスタンス上で動作させることができます。

これでnode.jsとSignalRはどちらも既存のコードをほとんど修正することなく、クラウドサービスでスケールアウトさせることができますね。

node.jsとSignalRの特徴と違い

node.js+socket.ioとSignalRは非常に似ている技術であることはすでにわかっていただけたと思いますが、やはり両者ともに特徴があります。

ここではにしてまとめてみたいと思います。

node.js+socket.ioSignalR
開発言語はJavaScript開発言語はC#、VB
サーバはnode.jsサーバはIIS
シングルスレッドで動作マルチスレッドで動作
ノンブロッキングI/Oを使った非同期スレッドプールを使った非同期
イベントベースのAPIRPCベースのAPI
Redisを使ったスケールアウトRedisとサービスバスを使ったスケールアウト
公式のクライアントはJavaScript公式のクライアントはJavaScriptとC#
コンパイルが不要コンパイルが必要
日本語の情報が豊富日本語の情報が少ない
運用実績が多い運用実績は少ない
node.js専用のホスティングサービスが存在しているIIS 8と.NET 4.5が使える環境は国内ではまだ少ない

node.jsのほうが情報や実績、そしてホスティングサービスの存在が非常大きいので、実際にアプリケーションを開発して、公開するのは有利だと思います。すでに開発者の人口が多いというのは、これから学ぶ人にとっても心強いですね。

パフォーマンスに関してはSignalRの方がマルチスレッドで動作する点や、パフォーマンスモニタ用の機能を備えているので環境によっては有利となるケースがあると思います。node.jsもクラスタ化することでマルチコアCPU上でのパフォーマンスを改善できますが、ひと手間加える必要があります。

このように説明してしまうと、まだまだ導入するには早いと考える方もいるかもしれません。しかしながら、両者ともにまだまだ発展途上で、さらに勢いのある技術なので、パフォーマンスやノウハウに関しては近いうちには解消されていくと考えていて良いと思います。

まずはどちらかの興味を持った技術から、実際に手を動かして試すことがリアルタイムWebを極める第一歩です。この連載をきっかけに興味を持ってくれた方がいれば、とても嬉しく思います。

おすすめ記事

記事・ニュース一覧