Traditionally HTTP has always been all about request/response architecture. If the client wants to receive some information, it issues a request and then the server gives back the response.
Imagine something that is actually updating the data in real time, for instance, NHL scoreboard. The score there doesn’t change so much, so what we would typically do is we issue a request, and then, after some time ask “Has there been any changes?”, “Any changes yet?”… That’s the typical web-based model of communication.
This approach is not very scalable. There are some times when you actually want to get notifications from the server without waiting for the completion of the request/response cycle. That’s where a platform like SignalR comes into place.
What is SignalR?
SignalR is an abstraction over the communication mechanisms. It is a set of libraries that are small and focused on building real-time web applications as well as client applications cross platform.
How it works?
With SignalR you can register for the messages that are going to be coming out from the server, and every time that the server wants to give the response, it will push that information out. From the point of view of the server-side developer, the idea of being able to push data to clients is really cool. It’s like you’re saying “Hey, here’s some new data for you”.
Unfortunately, that doesn’t work on the web, you can’t just go and push out updates to random clients. Here’s where SignalR comes to the rescue.
With SignalR onboard everything starts off with a simple HTTP request. Once it connects it does the handshake, creates the pipeline between the server and the client and then it sends the messages throughout the pipeline to individual clients or client groups. There’s also a possibility to stream data over channels. This approach creates a really nice mimicry of the client on the local network, so you get that real-time data flow feeling.
What protocols does it use?
Available protocols in classic SignalR for DotNet
By default it’s going to be using WebSockets protocol. But if the server or the client for whatever reason doesn’t support WebSockets then Long Polling is going to be used. It’s called a transport negotiation. Long Polling is when the client issues a request and keeps that request open until the server gives the response. As soon as it gets the response it immediately issues another request. Keep in mind that this is quite a memory heavy operation.
Of course you can specify the transport of your choice like Server-Sent Events or Forever Frame, but in general it’s going to try to go over the WebSockets, if it can’t then it’s going to pick something else. SignalR will just figure out the best way to connect and give you that live interaction.
What’s the difference between SignalR Core and SignalR shipped with .NET Framework?
This is a very common question or stumbling block for a lot of folks. SignalR classic version, or SignalR for DotNet and Asp.Net Core SignalR both have the same goals in mind and generally do the same things. Conceptually they’re the same. The development team tried to make it so programmatically they’re as close as possible, but they did got some major restructuring.
In older SignalR you’d have a hard dependency on jQuery on the client whether or not you’re using jQuery elsewhere, and it made sense at the time, because jQuery was pretty much in every project. But then jQuery fell out of favour and they removed it. But you can still use it or any other JS library if you want.
In the original SignalR you write hubs and underneath that was a thing called a Hub Dispatcher which was an implementation of something called “Persistent connection”. You basically have a pipe and you send messages back and forth.
With Asp.Net Core things are a little bit different. You now have your hub and underneath you have a thing called “Connection handler”. This is the thing that knows how to handle connections coming in on one side and then dispatch that off, create the hub instance, find the hub methods, pass those connections in. That’s all covered by
HubConnectionHandler. Underneath that you have this dispatcher type which is the thing that given a HTTP connection, turns that into the thing a hub connection handler can understand. And that all sits on top of routing which is used in MVC.
You may ask a question, why do we have all these layers in the new SignalR? Because SignalR, is server and transport agnostic. Old SignalR was tied to HTTP, it really wasn’t transport agnostic. All available transport protocols were HTTP based. We couldn’t do non HTTP protocols. But that’s not true with the new SignalR. It cares about connections. Now it can work with different server level transports like
Libuv. Today, we’re able to run SignalR over something that’s not HTTP, for example, directly over TCP. The stack is going to be a lot simpler in this case and will contain a lot less underlying layers.
Some other differences with the SignalR core:
- Global host was replaced with the DI
- Dropped ForeverFrame
- Separate connection for each hub
- Additional client libraries (for languages like Swift)
- Binary packages support
Strategies for scaling out
If we have hundreds or thousands of connections, you may notice that we’re passing a lot of data around. That may be problematic. So how do we scale that out? There’s a number of strategies.
In the old days there was a thing called the Backplane. But it wasn’t particularly good with multiple workloads, it was designed for a single workload.
The baseline strategy was to add a Backplane, so when the message gets sent up it then propagates to the Backplane, moves across the Backplane and then the server through the parallel tasks sends that to all of the clients. Really complex approach, a lot of code involved there.
Ideal situation for the user is to have a service in the cloud that manages all SignalR stuff for you. That’s what SignalR Service is. It is a PAAS (Platform As A Service) which manages all your SignalR connections. It’s built on Asp.Net Core SignalR Bedrock. It offloads all the SignalR connections from your app to the service so you don’t have to worry about load balancing Websocket connections and thinking about how to do that inside your Azure app. Then it takes all the traffic and relays all that back to your app. You can pick a scale that you need for HTTP traffic and SignalR traffic separately. It’s very easy to migrate an app to do this. SignalR Service can take care of all the scaling stuff.
Project Bedrock is a new networking abstraction for DotNet. It has a clear separation between application and transport layers. It takes the same idea used for HTTP and applies it to the idea of connections.
This allows to take Asp.Net Core and extend it beyond HTTP. The same app models, configurations, DI, hosting, but now you can just build server programs that don’t speak just HTTP. It is built on top of the new
System.IO.Pipelines API and does all memory management for you. Threading, polling, thread safety all this hard stuff is taken care of in Bedrock.
How can I get it?
How to set it up?
So first, you have to register middleware, in the startup class
useSignalR() inside of
Configure() method and then you’re mapping various hubs that you should be connecting to.
Typically you only need one hub for the project. And then you just route everything through that hub and manage your connections independently. More detailed getting started tutorial can be found in the article Tutorial: Getting Started with SignalR.
We’ve learned that SignalR allow us to build scalable, highly available, real-time applications. Examples of such apps can be social applications, multiuser games, business collaboration, and news, weather, or financial update applications. SignalR makes the process of building such apps simple and easy.
Hope this overview will help you figure out if this technology is right for your application. Oh yeah, if you build something with SignalR let me know! I’m @owlypixel on Twitter. I’d love to see what you’ve built. Cheers!