We have a SignalR hub called StatusUpdateHub. This hub is updated by a .NET client called HubClient. This client will be (in production) called about 1000 times per second by multiple users for different transactions. Here is the client code:
public static class HubClient
{
private static readonly string statusUpdateUrl = ConfigurationManager.AppSettings["StatusUpdateUrl"];
private static readonly HubConnection connection = new HubConnection(statusUpdateUrl);
private static readonly IHubProxy hub = connection.CreateProxy("StatusUpdateHub");
internal static void UpdateBrowser(long transactionId)
{
connection.Start().ContinueWith(task => hub.Invoke("UpdateTransactionStatus", transactionId)).ContinueWith(task =>
{
if (task.IsFaulted && task.Exception != null)
{
// log error
}
});
}
}
When this code is called with 100 concurrent users it is working fine but when we increase the number of concurrent users to 250 then we are seeing the following error:
Unexpected error in UpdateBrowser: System.InvalidOperationException: The connection has not been established. at SignalR.Client.Connection.SignalR.Client.IConnection.Send[T](String data) at SignalR.Client.Hubs.HubProxy.Invoke[T](String method, Object[] args) at SignalR.Client.Hubs.HubProxy.Invoke(String method, Object[] args) at Application.Services.HubClient.<>c_DisplayClass2.b_0(Task task1) in c:\Build\Work\Application\Services\HubClient.cs:line 20
at System.Threading.Tasks.Task`1.InvokeFuture(Object futureAsObj)
at System.Threading.Tasks.Task.Execute()
Let us know how we can make the code more scalable?
A SignalR app can scale out based on the number of messages sent, while the Azure SignalR Service scales to handle any number of connections.
In the default mode, the app server creates five server connections with Azure SignalR Service. The app server uses the Azure SignalR Service SDK by default. In the following performance test results, server connections are increased to 15 (or more for broadcasting and sending a message to a big group).
The default keepalive timeout period is currently 20 seconds. If your client code tries to call a Hub method while SignalR is in reconnecting mode, SignalR will try to send the command. Most of the time, such attempts will fail, but in some circumstances they might succeed.
If your SignalR application transmits sensitive information between the client and server, use SSL for the transport.
If that's the method being called 1000 times per second, you shouldn't be calling connection.Start()
every single time.
Open the connection only once, then just invoke methods on it.
Edit, what I mean is, at the very least, make your code do something like this:
internal static void UpdateBrowser(long transactionId)
{
lock (connection)
{
if (connection.State == ConnectionState.Disconnected){
connection.Start().Wait();
}
}
hub.Invoke("UpdateTransactionStatus", transactionId).ContinueWith(task =>
{
if (task.IsFaulted && task.Exception != null)
{
// log error
}
});
}
By default .NET allows 2 concurrent connections outgoing from client apps and 10 from ASP.NET apps. If you want to increase this number then set the http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.defaultconnectionlimit.aspx to a bigger number. See if that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With