Implementing a chat functionality in a web application using SignalR is not a difficult task, but there might be some problems along the way. A very important thing when it comes to implementing functionalities with the library is whether or not the application is going to be hosted on a single server or multiple servers. Another tricky part is how you map application users to the library’s connections. You can show the user once in a chat, but he can be logged in from more than one device, or even from more than one browser, using the same device. Still, the application can be opened in multiple tabs from the same browser. Here we will show you possible approaches to those problems and how you can solve them.
Fig. 1 Real-time web
Sessions in SignalR and sessions in your application are two different things and you have to find a way to map your users to SignalR connections. An easy way to do so is by moving the user’s details from the client side to the library’s code. There you’ll have both connection ID and user details and it’s you to decide how you will keep those things connected. One way to do it is by creating a static dictionary on your server, where you can use your user’s IDs as key. Here, the value of the dictionary can be a list of all connection IDs of this user. This way if a user is connected on multiple devices (phone, tablet, pc), you can easily send a message to all of them. Here is where the tricky part comes – the static dictionary is a very easy approach. However, it won’t work if you have multiple servers, because users connected to one server won’t see the users from other servers.
SCALEOUT IN SIGNALR
Sometimes when the load becomes too heavy, applications need to be scaled. There are two ways of doing this – scale up or scale out. Scale up means using a larger server with more RAM, CPUs, etc. Scale out means adding more servers to handle the load. The problem with scaling up is that there is a limit on the size of the machine and when it’s hit the only solution is to scale out. When you scale out your application, clients can get routed to different servers. This means, the client connected to one of the servers won’t see the client from other servers (Fig. 2 Server Scale Out). This is where SignalR scale out comes into play.
Fig. 2 Server Scale Out
One solution for this is using a component called backplane (Fig. 3 Use of Backplane). With this approach, all messages that are sent to one of the servers are also sent to this backplane. The backplane, then, sends it to all other servers.
Fig. 3 Use of Backplane
There are three backplanes that the library currently offers: Azure Service Bus, Redis and SQL Server. If you deploy your application on Azure, consider using the Redis backplane along with Azure Redis Cache. If you are deploying to your own server farm, consider SQL Server or Redis backplanes.
There are some limitations when using a backplane. The backplane is not recommended when the number of messages scales with the number of clients proportionally or when there is high-frequency realtime (e.g., real-time games).
When you need a real-time web functionality, SignalR is an easy and flexible solution. The most important thing you need to know is the expected load of the application, as it determines whether or not it will have to be scaled out to multiple servers. Which, in return, changes the approach – with a backplane or not. You need to keep in mind whether or not you want one client to be able to chat with another client in case they use the same user. You will also need to decide how you are going to store the connection between the SignalR session and the application session. All other details depend on the implementation and the needs of the application itself.
Dimitar Milanov (Technical Lead)