Search code examples
asp.net-mvc-4asp.net-web-apisignalrlong-polling

SignalR LongPolling crashes with a little of stress


I have a prototype that works well with SSE and WebSockets, but crashes when using LongPolling in the moment that I put a little bit of stress in the browser.

My app can create games, and each game generate its own events, and those events must be sent to the browser. I have a button to create one, ten and a hundred games at once. Create each game requires a POST call to a WebAPI, so the x10 button creates 10 requests and x100 creates 100 requests to the server.

When I use SSE or WS, it works nicely, I can call the x100 button and create a hundred games, all the games gets its respective events. I can see the 100 HTTP POST request being all successful.

But if I switch to LongPolling mode, I can create games one by one, as long I do not click too fast, and it works well. In the moment I click fast or click the "ten" or "hundred" button, all WebAPI calls but one get stuck and eventually fails with this message:

{"Message":"Anerrorhasoccurred.","ExceptionMessage":"Ataskwascanceled.","ExceptionType":"System.Threading.Tasks.TaskCanceledException","StackTrace":"atSystem.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__1.MoveNext()\r\n---Endofstacktracefrompreviouslocationwhereexceptionwasthrown---\r\natSystem.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\natSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Tasktask)\r\natSystem.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Tasktask)\r\natSystem.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()"}

Even running in debug, I cannot see that exception happening anywhere.

And SignalR disconnects:

[14:24:37 GMT+0000 (GMT Standard Time)] SignalR: Long poll complete. jquery.signalR-2.0.1.js:75
[14:24:37 GMT+0000 (GMT Standard Time)] SignalR: Disconnect command received from server. jquery.signalR-2.0.1.js:75
[14:24:37 GMT+0000 (GMT Standard Time)] SignalR: Stopping connection. 

And it is true, the server actually sends a D:1 in the last response, but I don't know why is that happening, I have nothing in my code that disconnects SignalR connections.

It happens in, at least, Google Chrome and IE 10.

I have no clue about what could be the problem. Any idea?

Cheers.

UPDATE:

I have created a small project that reproduces the issue. It have shared it here.

Accessing: http://localhost/LongPollingLoadTest/ we can add one game, ten or a hundred without problems, because it will use SSE or WebSockets if available.

Now, open http://localhost/LongPollingLoadTest/?transport=longPolling. You will see how most of calls gets stuck and also most of the times, the SignalR connection crashes.

I think the problem is somehow related with the groups management:

    [AcceptVerbs("POST")]
    public async Task<GameInfo> Post([FromBody]GameRequest request)
    {
        var game =new GameInfo() { Id = Guid.NewGuid(), Name = request.Name };
        if (_games.TryAdd(game.Id, game))
        {
            var context = GlobalHost.ConnectionManager.GetConnectionContext<MyPersistentConnection>();
            await context.Groups.Add(request.ConnectionId, game.Id.ToString());
            await context.Connection.Broadcast(game);
            Thread.Sleep(100);
            return game;
        }
        else
            throw new ArgumentException("Already exists");
    }

Solution

  • Issue already reported here as @dfowler indicated: https://github.com/SignalR/SignalR/issues/2456

    Cheers.