アプリが完成したら、コンシューマ向けの場合は一般に広く公開されることが多いと思うが、もしそのアプリに人気が出て1台のサーバだけでは処理しきれなくなった場合にはどうすればいいだろうか。これまでのWebアプリでは単純にWebサーバの台数を増やせば対応できていたのだが、SignalRなどのブロードキャストを行うリアルタイムWebアプリではそう簡単にはいかない。
Socket.IOやSignalRなどを用いた、サーバと常時接続するリアルタイムWebアプリでは、一般的にパブリッシュ・サブスクライブに対応したメッセージング・サーバを用意する必要がある。実際にSignalRで利用可能なメッセージング・サーバとしては、以下が挙げられる。
RedisやWindows Azureサービス・バスだけではなく、SQL Serverが利用可能なことを不思議に思うだろうが、SQL Serverでは「クエリ通知」という機構を利用して、アプリケーションからデータが変更されたことを検知可能だ。この仕組みを利用してSignalRではSQL Serverを使ったスケールアウトが可能となっているが、Windows Azure上のSQLデータベースではクエリ通知が使えないため、基本的にはオンプレミスでの運用限定と考えておけばいいだろう。
SignalR 1.1からはスケールアウトに必要な機能が内部的に共通化されていて、それ以前と比べると一貫性のある方法で設定することが可能だ。そして、各スケールアウト・プロバイダの切り替えも簡単に行えるため、「サービスの成長に従ってWindows Azureサービス・バスからRedisに切り替える」といったことも可能だ。
それでは実際に3種類のスケールアウト・プロバイダについて詳しく見ていくことにしよう。
Redisは最近非常に人気のあるKVS(Key-Valueストア)で、ほかのKVSにはない特徴としてPub/Sub型のメッセージング・システムを持っている。SignalRはこの機能を利用してスケールアウトを実現している。
Install-Package Microsoft.AspNet.SignalR.Redis
パッケージ・マネージャ・コンソールに上記のコマンドを打ち込むと、Redis用のスケールアウト・プロバイダがNuGetからインストールされる。インストールが完了したら、あとはアプリの初期化コードに以下のようなコードを追加するだけで、Redisを使ったスケールアウトが可能だ。
protected void Application_Start(object sender, EventArgs e)
{
// サーバ名、ポート番号、パスワード、使用するキーを指定する
GlobalHost.DependencyResolver.UseRedis("localhost", 6379, "", "SignalR.Key");
// Redis のデータベースを指定する場合にはこっちを使う
var config = new RedisScaleoutConfiguration("localhost", 6379, "", "SignalR.Key")
{
// Redis で使用するデータベースを指定
Database = 1,
};
GlobalHost.DependencyResolver.UseRedis(config);
}
ちなみにRedisスケールアウト・プロバイダはBookSleeveというRedisクライアント・ライブラリを利用している。RedisはSignalRのクライアント情報を格納する用途にも最適なので、積極的に使っていきたい。
Windows Azureサービス・バスは名前のとおりWindows Azureで提供されているメッセージング機能だ。「トピック」と「サブスクリプション」という2つの要素から成り立ち、ある程度のメッセージ量まではトピックの数を増やすことでスループットの向上が可能だ。
Install-Package Microsoft.AspNet.SignalR.ServiceBus
Redisの場合と同様にNuGetを使ってWindows Azureサービス・バス用のスケールアウト・プロバイダをインストールする。インストールが完了すれば、以下のように初期化コードを追加するだけでサービス・バスを使ったスケールアウトが可能だ。
protected void Application_Start(object sender, EventArgs e)
{
// サービスバスの接続文字列とトピックのプリフィックスを指定する
GlobalHost.DependencyResolver.UseServiceBus("Endpoint=sb://...", "SignalRApp");
// トピック数やメッセージの生存期間を指定する場合にはこっちを使う
var config = new ServiceBusScaleoutConfiguration("Endpoint=sb://...", "SignalRApp")
{
// サービスバスのトピック数を指定
TopicCount = 2,
// メッセージの生存期間を指定(ここでは 5 分)
TimeToLive = TimeSpan.FromMinutes(5)
};
GlobalHost.DependencyResolver.UseServiceBus(config);
}
Windows Azureサービス・バスを利用したスケールアウトは、メッセージング用のサーバを用意する必要がないので非常に簡単に開始できるが、メッセージ量が増えるとスケールしなくなってしまう点に注意が必要だ。
SQL Serverを利用したスケールアウトはサービス・バスやRedisよりも簡単にセットアップが可能だが、(繰り返しになるが)SQL Serverのクエリ通知を使っているため、Windows AzureのSQLデータベースでは実行できない点に注意が必要だ。
Install-Package Microsoft.AspNet.SignalR.SqlServer
インストールはこれまで紹介したプロバイダと同じくNuGetを使って行う。インストールが完了すれば、以下のように初期化コードを追加するだけだ。必要なテーブルなどは初回接続時に全て自動的に作成される。
protected void Application_Start()
{
// SQL Serverの接続文字列を指定する
GlobalHost.DependencyResolver.UseSqlServer("Data Source=...");
// テーブル数を指定する場合にはこっちを使う
var config = new SqlScaleoutConfiguration("Data Source=...")
{
// 使用するテーブル数を指定
TableCount = 2
};
GlobalHost.DependencyResolver.UseSqlServer(config);
}
テーブル数を増やすことで、ある一定のスループット向上が見込まれるが、あくまでもSQL Serverの一機能を使っているので、Redisやサービス・バスのようにスループットが向上するとは思わない方が無難だ。
SignalRには、本稿では紹介しきれなかった数多くの機能や、さまざまなプラットフォーム向けのクライアント・ライブラリなど、まだまだ用意されているのだが、今回の前編・後編を読んでいただくと実際にSignalRを使って新しいアプリを開発できるだろう。
今後リリースされるVisual Studio 2013ではSignalR回りが強化されることも発表されており、ASP.NETの中でも力が入れられているフレームワークだ。昨今のWebアプリ開発の世界では「MVCならRuby on Rails」「リアルタイム通信ならNode.js」といったように注目されているが、ASP.NETであれば、MVCもリアルタイム通信も同時に手に入るので、実は非常にお得なフレームワークなのだ。
リリースされて10年が経過したが、まだまだ進化を止めないASP.NETをこれからも注目していきたい。
Copyright© Digital Advantage Corp. All Rights Reserved.