Pregunta

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?

¿Fue útil?

Solución

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
        }
    });
}

Otros consejos

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top