こんにちは!!
オルターブースの 倉地 です。
本記事はオルターブース Advent Calendar 2024の13日目の記事です。(13日の金曜日です)
はじめに
.NETでリアルタイム通信を行うアプリを作ろうと思い通信処理に WebSocket を使おうと考えていたところ、「.NETでリアルタイム通信を実装する場合は、フォールバック等の考慮を含む接続処理やメッセージ送信処理を機能として備えており、WebSocket はもちろんそれ以外のプロトコルにも対応している SignalR がおすすめ」という情報を見つけました。今回は、その SignalR に関連して、 ASP.NET Core SignalR と Azure SignalR Service について説明します。
ASP.NET Core SignalR とは
ASP.NET Core SignalR でサポートしているプロトコルについて
ASP.NET Core SignalR では、以下の3つのプロトコルをサポートしています。
- WebSocket
- 双方向通信が可能なプロトコル
- Server-Sent Event
- サーバーからクライアントに一方向にデータを送るプロトコル
- LongPolling
- ライアントがサーバーにリクエストを送信し、新しいデータが利用可能になるまで接続を保持する方式
基本的には WebSocket を使用し、WebSocket が使用できない場合はほかのプロトコルを使用します。この方式によって、通常時は WebSocket で 高速な通信を行いながらも、WebSocket が接続できない場合は、ほかの汎用的な通信プロトコルを使用します。
ここまでは、ASP.NET Core SignalR でどのように通信プロトコルを扱うかについて考えてきました。
ここからは、ASP.NET Core SignalR で どのように接続・メッセージ送信を実現しているかについて説明を行っていきます。メッセージを送るための通信の実装を簡単にするハブと、通信する対象を指定できるユーザーとグループについて説明します。
ハブの話
ハブは、クライアントとサーバーが相互にメソッドを呼び出すことができるようにする、高レベルのパイプラインです。ハブはサーバーとクライアントの中間の、文字通りハブとして存在します。ハブが持っているメソッドはサーバー側からもクライアント側からも呼び出しを行うことができ、これを介してメッセージの送信などを行うことができます。
以下が Hub を継承してメッセージ送信を実装したメソッドの例です。このメソッドではすべてのクライアントにメッセージを送っています。
public async Task SendMessage(string user, string message) { await Clients.All.SendAsync("ReceiveMessage", user, message); }
ハブにある関数を呼び出すことで、WebSocket 、Server-Sent Event、Long Polling のいずれかで通信が行われますが、開発者はそれを意識する必要はありません。 通信プロトコルの選択は自動で行われます。
ユーザーとグループの話
ブロードキャスト的にユーザー全員と通信を行うこともできますが、 ユーザーを指定したり、グループを指定したりすることで決まった相手とだけ通信を行うこともできます。
以下はユーザーを指定して、メッセージを送る例です。
public Task SendPrivateMessage(string user, string message) { return Clients.User(user).SendAsync("ReceiveMessage", message); }
次の例はグループへの追加、削除を行い、メッセージを送る例です。
追加、削除されたタイミングでグループにいるユーザに通知が送られるようになっています。
public async Task AddToGroup(string groupName) { await Groups.AddToGroupAsync(Context.ConnectionId, groupName); await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has joined the group {groupName}."); } public async Task RemoveFromGroup(string groupName) { await Groups.RemoveFromGroupAsync(Context.ConnectionId, groupName); await Clients.Group(groupName).SendAsync("Send", $"{Context.ConnectionId} has left the group {groupName}."); }
このようにメッセージを送る相手を指定することで、効率的なメッセージングが可能になります。
Azure SignalR Service とは
次に、Azure SignalR Service について見ていきましょう。これまでの内容から、ASP.NET Core SignalR ライブラリを使用してリアルタイム通信アプリを自前実装できることがわかりました。それに対して、 Azure SignalR Service はどのような役割を担うのでしょうか?
ASP.NET Core を 単純に Web App にデプロイしたものと比較して、Azure SignalR Service も使用したアプリは以下のような特徴があります。
- 同時接続を効率的に行うことができる
- 通信部分を代行するため、アプリケーション自体は軽くなる
Azure SignalR サービスとは | Microsoft Learn
Azure SignalR Service を使うことによって自前アプリ実装から切り離される機能について解説します。
Azure SignalR Service では、接続管理を行ったりメッセージ配信を行ったりする部分を切り離しています。具体的に言うと、先ほど紹介したハブの部分が Azure SignalR Service に切り離され Azure SignalR Service がハブの役割を担うことで、サービス本体の負荷が高くならないようにしています。また、接続数が増えた場合も Azure SignalR Service は自動的にスケーリングを管理し、ハブはその上で動作するため、スケーリングの複雑さから解放されます。
ここまで、SignalR でどのように通信プロトコルを選択しているか、通信を行うためにどのような実装を行うかについて確認しました。そこで、公式のチュートリアルを通してチャットアプリを実装してみましょう。
実装してみた
Microsoft Learn のチュートリアル沿ってアプリを実装してみました。チュートリアルでは、 ASP.NET Core Blazor と ASP.NET Core SignalR を併用してチャットアプリケーションを作成しています。
ASP.NET Core Blazor は、クライアント側の UI を構築するためのフレームワークであり、ASP.NET Core SignalR はリアルタイム通信を実現するためのライブラリです。この2つを組み合わせることで、ブラウザ上で動作するリアルタイムチャットアプリケーションを実装しています。
チュートリアル通り進めると以下のようなアプリケーションを作成することができます。
Azure SignalR Service への接続
ASP.NET Core で作成したアプリを Azure SignalR Service に接続する方法を紹介します。
Azure SignalR Service への接続は、Visual Studio2022 でも行えます。
これで Azure SignalR Service に接続することができます。
まとめ
この記事では、ASP.NET Core SignalR や Azure SignalR Service を用いたリアルタイム通信の実装について解説しました。まず、WebSocket と SignalRの違いを説明し複数のプロトコル(WebSocket、Server-Sent Events、Long Polling)をサポートする利便性について触れました。ハブ機能やメッセージを送る対象を指定できるユーザーやグループについても確認しました。
さらに、Azure SignalR Service の利点についても説明しました。このサービスを利用することで、接続管理やメッセージ配信を効率化し、アプリケーションの負荷を軽減することができます。
また、今回紹介したチュートリアルでは、リアルタイムチャットアプリが簡単に作れることを確認できたと思います。ぜひ挑戦してみてください。
追記
Blazor Server を使用した対話型サーバー側レンダリング (対話型 SSR)では SignalR を使って、レンダリングを行っているようです。そのため、SignalR について理解することで、Blazor server についてもより深く理解することができそうです。 learn.microsoft.com
サービス一覧 www.alterbooth.com cloudpointer.tech www.alterbooth.com