This article will give you a complete insight into SignalR and how to implement the Real-time cache sync with NCache.
What is SignalR?
One client can communicate with other clients dynamically is possible with SignalR. When we are talking about web applications, one browser instance can somehow communicate with the other browser instances dynamically, which is made possible with SignalR. These kinds of applications are called real-time applications. It enabled the browser to update the data dynamically to reflect the latest data change as they happen in real-time.
How does SignalR work?
The real-time communication provided by SignalR is enabled by the concepts called Hubs and clients. The "Hub" is a class derived from the Hub base class that is present within the ASP.NET Core framework. It maintains connections with clients. Once the connection between the browser and the hub on the server has been established, the hub can communicate with the browser and the browser to the hub because the connection is two-way. The hub can act as a relay for all the connected clients once the client sends the message to the hub, and based on the new message, the hub could send a message to all the connected clients. Hub can be part of any ASP.NET Core server-side application.
SignalR uses RPC(Remote Procedure Call) principle to do its work. The procedure, in other terms, is called methods or functions, so SignalR makes it possible to call methods or functions remotely. SignalR uses the Hub Protocol that defines the format of the messages that go back and forth, just like HTTP is the protocol that can be used on a TCP connection. It uses the new WebSocket transport where available and gets back to the older one where it’s needed. WebSocket is a full-duplex and stateful protocol, which means the connection between client and server will stay alive until terminated by any one of them.
Use cases of SignalR
Chat System
IoT
Stock Market System
Any Game Score check application
Gaming Industry
Scaling Out SignalR
We use the web farm to scale out the SignalR application. Based on the above image, the web servers connect with the respective clients with a load balancer. Now with the SignalR, there is a web socket connection between the client and the server. From the above image, it’s obvious that client A is connected with Server A and clients B and C to the respective servers B and C. The main problem here is if the SignalR invokes some functionality on the client end, it would only do it for the currently connected clients; since there are multiple servers and multiple clients, and these clients can grow in the long run, there is a chance that lot of the clients have been missed because other web server has its respective clients, so each web server sends messages for the invocation of the methods through SignalR to it’s only connected clients through web socket. So you end up having inconsistent user experience from all the clients which are connected.
For example, if server A invoked some functionality, it would sync with Client A, B, and C but not with servers B and C. This will lead to inconsistent user experience. To overcome this issue, we can use SignalR backplane.
What is SignalR Backplane?
It is a shared bus, repository, or resource where all your web servers are connected. So, with Backplane, the web servers, instead of connected with the client by invoking the functions on clients, send the message to Backplane, and that will broadcast the message to all the web servers, and it broadcast to all the connected clients from this process you will achieve the consistent view and scalability factor.
Bottlenecks with SignalR Backplane
Database as a SignalR BackPlane is slow SignalR needs low latency
SignalR application with Backplane should be reliable; sometimes, using a database may lead to a single point of failure due to high load.
SignalR Backplane should be highly available; the unplanned outage may lead to service delivery issues.
We can overcome all these bottlenecks by using scalable In-memory distributed Cache. In this article, I’m going to explain the NCache, which provides a distributed linear scalability that will help us to overcome all the bottlenecks which we discussed earlier.
What is NCache?
NCache is an in-memory distributed cache for .NET, Java, and Node.js, and it is also open-source. NCache is super-fast and scalable and caches application data to reduce database trips. NCache is used to overcome the performance issues related to data storage, databases, and scaling the .NET, Java, and Node.js applications.
What is ASP.NET Core SignalR?
ASP.NET Core SignalR is a library for developers to implement the process to integrate real-time functionality. The library can be used to integrate any kind of real-time web functionality into your ASP.NET application. It can have server-side code push content to the connected clients immediately once it is available. It is an open-source Microsoft API.
Implementing Real-Time Cache Sync NCache as a Backplane and ASP.Net Core SignalR Application
I’m going to use my existing ASP.NET Core SignalR application for the demo. You can download the source code from GitHub. Please read this article to understand how to create an ASP.NET Core SignalR application.
Add the below JSON object in the appsettings.json file:
"NCacheConfiguration": {
"CacheName": "myLocalCache",
"EventKey ": "signalRApplication"
},
CacheName: Provide your newly created cluster cache name
ApplicationID: Give some unique string relevant to your application. It acts as an event key, and each client of the application will use the same key while using the invoking NCache extension method.
Download and install the package AspNetCore.SignalR.NCache from NuGet Package Manager or use the below command from the package manager console in Visual Studio.
Install-Package AspNetCore.SignalR.NCache
Add the below code to Program.cs file.
ConfigurationManager configuration = builder.Configuration;
builder.Services.AddSignalR().AddNCache(ncacheOptions => {
ncacheOptions.CacheName = configuration["NCacheConfiguration:CacheName"];
ncacheOptions.EventKey = configuration["NCacheConfiguration: EventKey"];
});
Now our application is connected with NCache, assume we have two web servers connected with NCache as a backplane.
The application which I have used is to collect the real-time temperature from different agriculture farms; in real-time, the data will come from an IoT device, but for a demo, I used the client-side data entry for the temperature update. Once the temperature is updated from one client, it will reach the SignalR hub; since the web server is connected with NCache, an In-memory distributed cache acts as a Backplane. It will sync the data with other servers, and the real-time data will reach all the clients.
The default Hub protocol is using JSON. The sample looks like the below statement.
{
“type”: 1
“target”: “Receiving a message”
“argument”: [{”id”:1, “NewTemperature”:29}]
}
Type 1 means that this is a function invocation.
Target is the name of the function, and argument is an array of parameters passed to the function.
Run the application and try it from two browsers as two clients and assume we have two web servers connected with NCache as a Backplane.
Update the temperature of farm B from 26 to 29. It will reflect across different clients.
Client Connection has been established, and now the NCache will act as a backplane for our SignalR application. Once the NCache initiates, you can see the client count in the NCache web monitor application, as shown in the below figure:
We have seen the basics of SignalR, the Backplane for SignalR to avoid the inconsistency in the real-time data across all the clients, and we found some bottlenecks with maintaining performance and avoiding the single point of failure with the conventional implementation of the SignalR with Backplane. To overcome these bottlenecks, we used NCache distributed Cache as a Backplane for our ASP.NET Core SignalR application to sync to real-time data and maintain user consistency across all the clients with high performance and no single point of failure.