Serverless real-time messaging with Azure Functions and Azure SignalR Service
One missing piece for me to go all in on serverless so far was the lack of real-time messaging to clients using for example websockets. Usually we do this using SignalR for ASP.NET Core but this requires to run e.g. inside a container or a Azure Web App.
Since I like writing Functions in C# I wanted to see if I can get this to work in C# as well and then connect it to a simple Angular client. So I wrote I little sample using Azure Functions in C# and Angular: https://github.com/GrillPhil/ServerlessRealtimeDemo
Step 1: Create a new Azure SignalR Service instance
Log into your Azure Portal (https://portal.azure.com/) and create a new resource of type SignalR Service.
For testing purposes the Free tier is enough. If it’s hidden when selecting the Pricing tier just click on “View all” in the upper right corner of the blade to reveal it.
After the service is created copy the connection string from the Keys section
Step 2: Create a Function App
Create a new Function App in Visual Studio
Choose Azure Function v2 Preview (.NET Standard) and the Http trigger template.
Next we add a reference to the Nuget package AzureAdvocates.WebJobs.Extensions.SignalRService Anthony Chu has created that provides us with the required bindings.
We will need 2 functions: One to provide a SignalR endpoint to our client (negotiate) and one to allow to post messages to the SignalR service using a http request (message). Both functions will need the connection string of the SignalR service we just created. The default settings name is AzureSignalRConnectionString, so lets add this to our local.settings.json for local testing and later to our application settings in Azure.
In order to be able to call this function locally from our Angular app we also need to enable CORS by adding a Host section with a wildcard CORS policy.
This function will be called by our client to retrieve the SignalR Service endpoint. To do so we need to create a new function with a Http trigger and inject an
AzureSignalRConnectionInfo object using the
SignalRConnectionInfo attribute. In the attribute we need to specify the name of the hub we intend to use, e.g.
[SignalRConnectionInfo(HubName = “broadcast”)]AzureSignalRConnectionInfo info. This object provides the endpoint url that we then can simply return.
This function will be called to broadcast a message to all connected clients through our SignalR Service. Therefore we will create a new function with a Http trigger and this time inject a
IAsyncCollector<SignalRMessage> object using the
SignalR attribute and specifying the same hub, e.g.
[SignalR(HubName = “broadcast”)]IAsyncCollector<SignalRMessage> signalRMessages. To actually send a new message we then need to call
AddAsync on the
IAsyncCollector<SignalRMessage> and provide a new
SignalRMessage as parameter. The property
Target is the SignalR method we want to call.
And that’s it for the function part!
Step 3: Create an Angular Client App
Now let’s spin up a new Angular app that acts as our demo client to send and receive messages. We can do this e.g. by using the Angular CLI.
We need to add the @aspnet/signalr package to our project e.g. using npm.
Let’s now create a new service to handle all things SignalR in our app. This service will need an init method to get the SignalR endpoint from our function app by calling the negotiate function and then establish a new
hubConnection. After we have established the connection to our SignalR hub we can then start to listen for new messages.
The second method we will need is a send method to trigger our message function and create a new message.
Now we can inject the
SignalRService into a component, connect it to a sample UI and subscribe to new messages.
So let’s try this with multiple browser windows and enjoy!
Again the full demo is available on Github: https://github.com/GrillPhil/ServerlessRealtimeDemo
With just a few lines of code we can setup a complete serverless real-time messaging system in Azure using Azure Functions and the new Azure SignalR Service at scale.
For more information check out: