こんにちは、サイオステクノロジー 技術2部 水倉です。
Microsoft Build 2019 2日目のセッション「Bring serverless apps to life with Azure SignalR Service」を聞いてみて、SignalR の概要と Azure SignalR Service の Service Mode を整理してみたいと思います。
SignalR とは?
Web でリアルタイムな動作を実現するための技術です。基本的に通信プロトコルは WebSocket を利用しますが、クライアントが対応していない場合は Server-Sent Events や、ロングポーリングなどが利用されます。SignalR がサーバーとクライアントでサポートされる機能をベースに最適な通信方式を自動検出するため、開発者は実際の内部通信を意識する必要のない抽象化されたリアルタイム Web 技術となっています。
SignalR を利用することで、非同期通信で技術的な複雑度が高いリアルタイムなアプリケーションの開発のハードルを下げられます。具体的には次のようなアプリケーションに向いています。
- サーバーからの頻繁な更新が必要なアプリ
- ゲーム、投票、マップ(GPS)、監視ダッシュボードなど
- 双方向性のコラボレーションアプリ
- 同時通訳、ホワイトボードへの同時描画など
- 頻度の高い通知が必要なアプリ
- SNS、電子メール、チャットなど
全てのクライアント、特定グループ、特定ユーザへのプロードキャストも簡単に実装できるので、デモ映えするサンプルアプリを作ってみるのもいいと思います。
ASP.NET Core SignalR サーバーアプリケーションとクライアントとの接続は下記のような直接接続です。Hub を介した RPC (Remote Procedure Call) で、サーバーからクライアントメソッドの呼び出し、クライアントからサーバーメソッドの呼び出しという相互の処理を呼び出すことを実現しています。(図ではサーバーサイドが App Service になっていますが、何でもよいです)
Azure SignalR Service とは?
SignalR のマネージド・サービスが Azure SignalR Service です。前述の ASP.NET Core SignalR サーバーで自己ホスト型だった SignalR サービスが PaaS になったものが Azure SignalR Service です。
SignalR Service 作成時にちょっとわかりづらいのが Service Mode です。
Default、Serverless、Classic が選択可能ですが、PaaS で Serverless ってどういうこと・・?、ちょっとイメージが湧きづらいですね。
Azure SignalR Service でのクライアントとサーバーの接続方式について
Azure SignalR Service の場合、SignalR サーバーアプリケーションはクライアントからの接続を受け入れる必要がなくなります。以降、「SignalR サーバーアプリケーション」は「サーバー」と表記します。
- クライアントはサーバーへ接続のネゴシエーション要求を送る。
- サーバーは Azure SignalR Service へリダイレクト(アクセストークンと共に)する。
- クライアントは Azure SignalR Service と永続的な接続を確立する。
- この際、当該クライアントとの接続に使用するサーバーが検索され、クライントとサーバーのマッピング定義が保持される。
クライアントとサーバー間のデータ転送は、Azure SignalR Service を経由して行われます。サーバーでは、クライアントへの接続は抽象化され、クライアントとの接続状態を考慮することが不要となりますので、ビジネスロジックの実装をすればよい形になります。
また、多数のクライアントとの永続的な接続に対してスケーラビリティや可用性を確保するには考慮すべきことが多いですが、Azure SignalR Service を利用することで、その辺りをお任せできるのも大きなメリットになります。
さらに、Azure Functions の SignalR Service バインディングを利用すれば、外部イベントを検知して、クライアントにリアルタイムプッシュする仕組みをサーバーレスで実装可能です。
Azure SignalR Service の Service Mode に話を戻します。
元々、Azure SignalR Service は一律 Classic モードで動作していました。Classic モードでは、クライアントとの接続が利用可能であればサーバー接続、接続可能なサーバーがなければクライアント向け API モードで動作するという動きをします。この場合、サーバーがダウンしても、Azure SignalR Service とクライアントとの通信はクライアント向け API モードで接続が維持される状態になるため、クライアント側ではエラーが検知できない状況でした。
この点に対する対応として、Default モード、Classic モードが追加された経緯があります。
Service Mode | 説明 |
---|---|
Default | Hub を実装したサーバーが必須。Hub に対して利用可能な接続がない場合、クライアントとの接続が切断される。(クライアント側でエラー検知可能) |
Serverless | Hub サーバー利用不可。サーバーからの接続そのものを許可しない。(接続自体がエラーになる) |
Classic | サーバー接続が利用可能な場合はサーバー接続、利用不可の場合はクライアント向け API モードで動作。接続が切断されることもなく、エラーにならない。 |
ということで、ASP.NET Core SignalR サーバーアプリケーションで Azure SignalR Service を利用する場合は Classic、Azure Functions の SignalR Service バインディングを利用する場合は Serverless を選択すればいいことになります。
(※) こちらの記事を参考にさせていただきました。
最後に
SignalR が登場した時、リアルタイム Web のプログラミングのハードルが大分下がったなぁと感じましたが、それでもまだ Hub サーバーのスケーラビリティ、可用性を担保するのはそれなりのコストでした。Azure SignalR Service を使うことで、インフラレイヤーの設計・運用要素が減り、よりコードに集中できることがわかりました。サーバーレスでクライアントへのリアルタイムなブロードキャストを実現できるお手軽感はすごいですね。動きのあるサンプルが簡単に実装できる楽しいサービスです。
STI 水倉