dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.49k stars 10.04k forks source link

SignalR connection gets terminated after 5 minutes in Chrome #31079

Closed mgazell closed 3 years ago

mgazell commented 3 years ago

I'm facing an issue maintaining a signalR connection using the @microsoft/signalr client package. After establishing a connection and 5 minutes of tab inactivity (user active in another tab or window), the connection gets closed. This seems to be related to recent policy changes in Chrome (JavaScript throttling) forcing WebSocket connection termination in 5 minutes of tab inactivity.

You can reproduce this issue using this serverless signalR sample at docs.microsoft.com

The only change that I did on the sample was to change the reference from @aspnet/signalr to @microsoft-signalR in the index.html file

Please see snip from my console below.

image

BrennanConroy commented 3 years ago

I can't repro this issue, what OS are you on? What version is the OS? Did you make any more modifications to the app?

mgazell commented 3 years ago

I'm on Windows 10 (version 1709) and using Chrome (Version 89.0.4389.90 (Official Build) (64-bit))

No, I didn't make any other change other than the script reference change that I highlighted.

Davilink commented 3 years ago

I can't repro this issue, what OS are you on? What version is the OS? Did you make any more modifications to the app?

I was able to reproduce this issue with Chrome on Windows like every single time:

  1. Open a tab using signalr with websocket
  2. Wait for the connection to be established
  3. Switch a tab
  4. Minimize Chrome
  5. Wait 5 minutes (10 minutes to be sure)
  6. Go back to the original tab
  7. Websocket is disconnected

I try to reproduce it on Chrome Linux, but i was under the impression that wasn't reproducible under Linux, but i did...only 1 time, and i cannot reproduce it anymore... (really strange), but on Chrome Windows it's every time.

Other reproduce step: https://github.com/SignalR/SignalR/issues/4536#issuecomment-802970408

Davilink commented 3 years ago

Workaround using the « Page Visibility Api » (https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API)

const connection: HubConnection = new HubConnectionBuilder()
  .withUrl('/hub/MyHub')
  .build();

document.AddEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible' && connection.state !== HubConnectionState.Connected) {
    connection.start();
  }
}

Note: This workaround will not work for all use case because you lose data when the connection is drop. Other thing to take into consideration is the fact that it's a new connection, so if you are using groups, you will need to resubscribe to the group

IanYates commented 3 years ago

Workaround using the « Page Visibility Api » (https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API)

const connection: HubConnection = new HubConnectionBuilder()
  .withUrl('/hub/MyHub')
  .build();

document.AddEventListener('visibilitychange', () => {
  if (document.visibilityState === 'visible' && connection.state !== HubConnectionState.Connected) {
    connection.start();
  }
}

Note: This workaround will not work for all use case because you lose data when the connection is drop.

Good point about the data loss, but it's at least helpful to have the notification of the issue so we might be able to tell the user to expect issues. Thanks!

mgazell commented 3 years ago

Hi @BrennanConroy ,

Are you still not able to repro the issue? Please let me know if you need more inputs.

Vikki123 commented 3 years ago

We are also facing the same issue. We are also seeing the same behavior once the tab is minimized for 5 mins. We do not support re-connect option as its not feasible for the use case. Any workaround to keep the ping alive ?.

We are using @microsoft/signalr": "3.1.2

prasadmamidi7 commented 3 years ago

I am also facing same problem

Use case

Application version

Chrome Browser: Version 89.0.4389.90 (Official Build) (64-bit) Asp.net core : 3.1.2 Angular -signalr core :3.1.2

Note: this behaviour is not observed on Microsoft Edge and Firefox .

Any workaround much appreciated.

BrennanConroy commented 3 years ago

Are you still not able to repro the issue?

Still can't repro, We have a rough idea of where there could be an issue with the library with the new Chrome "feature", so we'll try to figure something out there. And probably rely on the community to test it out :)

Any workaround much appreciated.

A workaround would probably be to change the server-side and client-side timeout values to be over 1 minute.

Vikki123 commented 3 years ago

@BrennanConroy I quite dint understand how increasing the timeout to 1min would solve this issue. Isnt it going to fail anyways after one min as the connection is disconnected already due to inactivity.?

Vikki123 commented 3 years ago

@BrennanConroy I quite dint understand how increasing the timeout to 1min would solve this issue. Isnt it going to fail anyways after one min as the connection is disconnected already due to inactivity.?

Davilink commented 3 years ago

Other workaround: using the onclose event

let isCloseRequested = false;

const connection: HubConnection = new HubConnectionBuilder()
  .withUrl('/hub/MyHub')
  .build();

connection.onclose(error => {
  if (!isCloseRequested) {
    setTimeout(() => connection.start(), 0);
  }

  if (error) {
    console.error(error);
  }
});

export function start(): Promise<void> {
  isCloseRequested = false;
  return connection.start();
}

export function stop(): Promise<void> {
  isCloseRequested = true;
  return connection.stop();
}

Note: This workaround will not work for all use case because you lose data when the connection is drop. Other thing to take into consideration is the fact that it's a new connection, so if you are using groups, you will need to resubscribe to the group.

UPDATE: attempt to fix the « resubscribe to the group »

let isCloseRequested = false;
let reconnectFn: (() => Promise<void>) | null = null;

const connection: HubConnection = new HubConnectionBuilder()
  .withUrl('/hub/MyHub')
  .build();

connection.onclose(error => {
  if (!isCloseRequested) {
    setTimeout(() => connection.start().then(() => reconnectFn?.()), 0);
  }

  if (error) {
    console.error(error);
  }
});

export function start(): Promise<void> {
  isCloseRequested = false;
  return connection.start();
}

export function stop(): Promise<void> {
  isCloseRequested = true;
  return connection.stop();
}

export function join(roomId: string): Promise<void> {
  reconnectFn = () => connection.invoke('JoinRoom', roomId);
  return reconnectFn();
}

export function leave(roomId: string): Promise<void> {
  reconnectFn = null;
  return connection.invoke('LeaveRoom', roomId);
}
andrew-tevent commented 3 years ago

I hope I'm not hijacking this, but I am seeing something similar in my Blazor WebAssembly app - in that the SignalR Core Client stops responding to KeepAlives from the server. The server, not seeing a response within the KeepAlive Timeout closes the connection - the client immediately reconnects (I have auto reconnect on)

image

This appears to be, like described, when the user isn't necessarily active in the app. It is quite easily reproducible (but not every time for some reason)

ghost commented 3 years ago

Thanks for contacting us. We're moving this issue to the Next sprint planning milestone for future evaluation / consideration. We will evaluate the request when we are planning the work for the next milestone. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

sonnywood commented 3 years ago

I was working on this issue last week. We have a telephony application using Signalr to push messages to the browser. I am tracking every connect, reconnect, and disconnect from the server. I was lucky enough to be working on a laptop with low memory so this issue was more pronounced in my situation. I have Windows 10 with 4GB and 85% used. It appears that browser updates to Chrome, Edge, Firefox etc. have come with a new feature to suspend activity on inactive tabs when memory is low.

In my testing:

Firefox

Firefox_SleepingTabs_Settings Firefox_Logs

Edge

Edge_SleepingTabs_Settings Edge_Logs

Chrome

Chrome_SleepingTabs_Settings Chrome_Logs

IanYates commented 3 years ago

@sonnywood - that's a good summary. Thanks!

jahmai-ca commented 3 years ago

Thanks for the great info @sonnywood! I am seeing something very similar, in that Chrome lists our signalR websocket being reconnected periodically (between every 1 and 5 minutes).

WayneHiller commented 3 years ago

This is also happening in the "Microsoft.AspNetCore.SignalR.Client" Version="5.0.4" in a Blazor Wasm app.

BrennanConroy commented 3 years ago

Oh right, thanks for mentioning that. I thought about it last night but then forgot today :)

WayneHiller commented 3 years ago

For reference I was able to manually fix the issue in a JS client (jquery.signalR-2.4.0.js) using this pull request.

https://github.com/SignalR/SignalR/pull/4544

BrennanConroy commented 3 years ago

If anyone is interested in using the latest build with the fix, you can find it at https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/npm/6.0.0-preview.4.21208.10/microsoft-signalr-6.0.0-preview.4.21208.10.tgz

WayneHiller commented 3 years ago

@BrennanConroy Will that build work ok in a Net 5.0 project? If so I will test it out

BrennanConroy commented 3 years ago

It's a javascript library, so it doesn't matter what .NET you're using.

andrew-tevent commented 3 years ago

I put details about Blazor Wasm in an earlier post.

Is this fix really only going in .net 6 ? Forgive me for my ignorance, but how do I just update the JS part?

davidfowl commented 3 years ago

Is this fix really only going in .net 6 ? Forgive me for my ignorance, but how do I just update the JS part?

Once we fix the issue you'll be able to get it from npm.

andrew-tevent commented 3 years ago

@davidfowl Thanks for the quick response.

What I mean is, currently my Blazor Wasm is just referencing the SignalR package:

<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.4" />

I'm not including any JS directly in my app - I presume the .net assembly takes care of outputting that to the browser. So how do I override this with the fix?

Vikki123 commented 3 years ago

Thanks for the quick responses. Just wanted to check if there is any plans to backport the fix to older versions ? We are in the final stages of the project and migration to a new major version might not be an option we have. We are currently using @microsoft/signalr": "3.1.2.

sonnywood commented 3 years ago

We are using the old ASP.NET Signalr JavaScript Library v2.3.3. Do you know if this will work in place of that library? If the fix will work for my case I will run it through some tests.

andrew-tevent commented 3 years ago

@sonnywood @Vikki123 This repo is for AspNetCore - the older Net Framework SignalR issue is being tracked here and the PR for the fix is here.

WayneHiller commented 3 years ago

@BrennanConroy Sorry I did not look close enough at the filename. As @andrew-tevent noted above Blazor Wasm just uses the .Net Aspnetcore client which in turn must be using a similar short duration chained setTimeout calls as all the SignalR JS does.

BrennanConroy commented 3 years ago

Sorry, but the blazor wasm fix is going to take longer. The current fix is only for users of the @microsoft/signalr npm package.

Just wanted to check if there is any plans to backport the fix to older versions ?

We are trying to backport to 3.1 and 5.0.

Davilink commented 3 years ago

@BrennanConroy

We are trying to backport to 3.1 and 5.0.

Do you have a ETA ?

mgazell commented 3 years ago

Hi @BrennanConroy

Thanks again for fixing this.

The current version out on npm is 5.0.5. What version of the @microsoft/signalr npm package would have this fix? When would that get released?

BrennanConroy commented 3 years ago

Do you have a ETA ?

What version of the @microsoft/signalr npm package would have this fix? When would that get released?

We'll be shipping 6.0.0-preview4, 5.0.6, and 3.1.15 next month. I'll link to previews of those releases when we get builds of them, hopefully later today.

BrennanConroy commented 3 years ago

Pre-released bits:

Version Url
6.0.0-preview4 https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/npm/6.0.0-preview.4.21208.10/microsoft-signalr-6.0.0-preview.4.21208.10.tgz
5.0.6 https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/npm/5.0.6-servicing.21212.4/microsoft-signalr-5.0.6.tgz
3.1.15 https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/npm/3.1.15-servicing.21212.3/microsoft-signalr-3.1.15.tgz
WayneHiller commented 3 years ago

@BrennanConroy

Sorry, but the blazor wasm fix is going to take longer. The current fix is only for users of the @microsoft/signalr npm package.

Do you know if there is a separate Issue to follow for the .Net Aspnetcore Client fix?

IanYates commented 3 years ago

@BrennanConroy

Sorry, but the blazor wasm fix is going to take longer. The current fix is only for users of the @microsoft/signalr npm package.

Do you know if there is a separate Issue to follow for the .Net Aspnetcore Client fix?

See this issue: https://github.com/dotnet/runtime/issues/51041 @WayneHiller

mgazell commented 3 years ago

5.0.6 https://dotnetcli.blob.core.windows.net/dotnet/aspnetcore/npm/5.0.6-servicing.21212.4/microsoft-signalr-5.0.6.tgz

I have tested with the prerelease version and the connection does not get terminated now after 5 minutes of tab inactivity!

planty commented 3 years ago

We've been having issues with disconnects every few minutes too, so I tested the 3.1.15 prerelease earlier and can confirm that seems to have resolved the issue. Thanks for fixing @BrennanConroy

mgazell commented 3 years ago

Workaround using the « Page Visibility Api » (https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API)

A workaround that we are using in the interim that works is to enable auto reconnect when building the connection. I'm not sure if data is lost and I didnt check as it's not a concern for our use case.

connection = new signalR.HubConnectionBuilder() .withUrl(info.url, options) .withAutomaticReconnect() .build();

tofron commented 3 years ago

We've been having issues with disconnects every few minutes too, so I tested the 3.1.15 prerelease earlier and can confirm that seems to have resolved the issue. Thanks for fixing @BrennanConroy

i couldn'd found 3.1.15 prerelease on nuget?

BrennanConroy commented 3 years ago

Right, there isn't a nuget package, there are only npm packages which are linked above https://github.com/dotnet/aspnetcore/issues/31079#issuecomment-818294813

Vikki123 commented 3 years ago

When is the release planned for this fix ? Any ETA ?

BrennanConroy commented 3 years ago

3.1.15, 5.0.6, and 6.0.0-preview4 later this month

GREsau commented 3 years ago

For the benefit of anyone watching this issue, versions 3.1.15 and 5.0.6 of the SignalR client are now on NPM: https://www.npmjs.com/package/@microsoft/signalr

tofron commented 3 years ago

For the benefit of anyone watching this issue, versions 3.1.15 and 5.0.6 of the SignalR client are now on NPM: https://www.npmjs.com/package/@microsoft/signalr

i Just update using NuGet. And after 5 minutes inactive tab it stop. same as before. Im Using blazor webassembly. Im Using version 3.1.15

davidfowl commented 3 years ago

@tofron Did you also update using NPM or are you talking about the C# client?

tofron commented 3 years ago

@tofron Did you also update using NPM or are you talking about the C# client?

im using visual studio. i am updating signalR.Client using Nuget Package. Not using NPM

davidfowl commented 3 years ago

The nuget package contains the .NET dlls but it doesn't contain the javascript (where the fix is). Are you using the javascript client? How did you get it in the first place?

BrennanConroy commented 3 years ago

And after 5 minutes inactive tab it stop. same as before. Im Using blazor webassembly

Blazor WebAssembly is not fixed yet.

Sorry, but the blazor wasm fix is going to take longer. The current fix is only for users of the @microsoft/signalr npm package.

https://github.com/dotnet/aspnetcore/issues/31079#issuecomment-816743871

You have already seen the issue for this at https://github.com/dotnet/runtime/issues/51041