SignalR Performance and Scaleout configuration.

Hi again,

In this blogpost, I want to share with you, what you can do on a distributed SignalR environment, to improve performance.

After working on a number of SignalR related performance issues, i saw that scale-out configuration was helping to resolve connectivity problems. When you have increased contention on backplane (ie. Locks on backplane database) it can result delay on message transmission, and even can cause connection failures on client side.

Backplane implementation is mostly recommended on “Server Broadcast” type of applications. Not limited to these, other type of implementation are; “Client-to-Client” type or “High-Frequency Realtime” applications. One thing we usually try for performance considerations is; to change scale-out configuration for the backplane. The intentions for making this configuration is to increase the count of streams to backplane. For SQL backplane configuration, it means increasing the tableCount and for ServiceBus backplane it’s the TopicCount. For “Redis backplanes”, indeed we don’t have an option to increase stream count, but for all the type of backplane configurations “QueueLenght” parameter effectively (Queue infront-of backplane) helps improving performance. For an issue I have worked before, increasing “QueueLenght” on RedisBackplane has resolved connectivity issues, especially for ‘LongPolling’. I can say that, "scale-out configuration" is important since the clients progress on reading messages through the bus with a cursor value, and it effects end-to-end real-time behaviour. Here is a typical “SqlScaleoutConfiguration” that increases the table/stream count from “1” (Default) to “3” from this article:

var connectionString = "(your connection string)";
var config = new SqlScaleoutConfiguration(connectionString) {
TableCount = 3,
MaxQueueLength = 50 };
GlobalHost.DependencyResolver.UseSqlServer(config);

After this configuration is activated, you can check database and you will see the parallelity, in action:

See supplementary articles below for backplane configuration and scaling out:

Code implementations from ‘master’ branch:

https://github.com/billboga/SignalR-1/blob/master/src/Microsoft.AspNet.SignalR.Redis/RedisScaleoutConfiguration.cs https://github.com/billboga/SignalR-1/blob/master/src/Microsoft.AspNet.SignalR.ServiceBus/ServiceBusScaleoutConfiguration.cs https://github.com/billboga/SignalR-1/blob/master/src/Microsoft.AspNet.SignalR.SqlServer/SqlScaleoutConfiguration.cs

Classes from msdn:

https://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.servicebusscaleoutconfiguration(v=vs.118).aspx https://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.redisscaleoutconfiguration(v=vs.118).aspx https://msdn.microsoft.com/en-us/library/microsoft.aspnet.signalr.sqlscaleoutconfiguration(v=vs.118).aspx

Articles on scaleout configuration:

https://www.asp.net/signalr/overview/performance/signalr-performance#tuning

From Article:  “A Stream in this context is a scale unit used by the scaleout provider; this is a table if SQL Server is used, a Topic if Service Bus is used, ..” https://www.asp.net/signalr/overview/performance/scaleout-in-signalr

From Article: “Each server instance connects to the backplane through the bus. When a message is sent, it goes to the backplane, and the backplane sends it to every server. When a server gets a message from the backplane, it puts the message in its local cache. The server then delivers messages to clients from its local cache.. client’s progress in reading the message stream is tracked using a cursor.”

 

Finally, to see if you require parallelity on backplane, you can configure SignalR Performance counters. You can check my blog on that.

Hope it was helpfull,

Mert