Skip to content

Understand when disconnections are graceful or not #12828

Closed
@SteveSandersonMS

Description

@SteveSandersonMS

I'm splitting this out of comments in #12788 so we track dealing with this specifically. Since implementing the graceful disconnect support, we don't know in which real-world scenarios reconnection will be attempted or not.

Relevant comments:


@SteveSandersonMS:

Is the event of an ungraceful disconnection common?

I'd go further and check we can prove it's even possible in the real world, not just tests.

  • If you deploy an app to Azure, connect through wifi (e.g., on a phone), then walk out of range of the wifi signal, does that cause a graceful or a disgraceful disconnect?
  • Which one happens if you switch the phone into flight mode?
  • Which one happens if you're on a laptop and close the lid?

We ought to be sure that disgraceful disconnects are the common case (except when genuinely closing the browser/tab), otherwise we've invested a lot into a feature that will never be used.


@SteveSandersonMS
There is a different technical solution here, which is to only do a "graceful disconnect" when we receive the beacon from an unload handler. That bypasses all the uncertainty about whether the network traffic is right about whether the user really intended to disconnect.

Drawbacks to using beacon:

  • Doesn't cover the case where the browser crashes (we'd keep the circuit open, even though there's actually no hope of reconnecting)
  • Doesn't work if you lack client-server affinity, since the beacon could go to any server
  • Makes it much easier to fill the server with abandoned circuits, since you can just choose not to send the beacon. The existing design is harder to trick because you need to leave a half-open connection, which involves dropping down to a very low level in the network stack, beyond what most networking APIs allow.

@javiercn

  • Doesn't work if you lack client-server affinity, since the beacon could go to any server

Reconnection wouldn't work either.

  • Makes it much easier to fill the server with abandoned circuits, since you can just choose not to send the beacon. The existing design is harder to trick because you need to leave a half-open connection, which involves dropping down to a very low level in the network stack, beyond what most networking APIs allow.

Re-connection is best effort and we can always remove the circuits in a FIFO fashion.

  • Doesn't cover the case where the browser crashes (we'd keep the circuit open, even though there's actually no hope of reconnecting)

If the browser crashes I think it would be treated as a graceful disconnect in the current scenario.

I'd go further and check we can prove it's even possible in the real world, not just tests.

  • If you deploy an app to Azure, connect through wifi (e.g., on a phone), then walk out of range of the wifi signal, does that cause a graceful or a disgraceful disconnect?
  • Which one happens if you switch the phone into flight mode?
  • Which one happens if you're on a laptop and close the lid?

We ought to be sure that disgraceful disconnects are the common case (except when genuinely closing the browser/tab), otherwise we've invested a lot into a feature that will never be used.

I still think there are ways we can cause it to be ungracefully terminated, the main thing is that it won't be treated as ungraceful unless you are in the middle of receiving a message.

  • For example, if we throw while waiting for a message to arrive, it won't be considered ungraceful, and that might happen either due to a network loss or the browser being closed.
  • If we throw after we've read the header but not the entire payload, that can cause the server to barf too.

I plan to physically try some of these things:

  • Turn of phone wifi.
  • Turn on airplane mode.
  • Go away from wifi range.
  • Kill browser process.

Update:
I managed to make this work in test scenarios. It involves a bit of trickery, but it works. We provide our own IHttpWebSocketsFeature, it does the same thing that the WebSocketsMiddleware one does.

  • We wrap the websocket it creates with a test socket of our own we can use to trigger exceptions whenever we want.
  • We do this conditionally on tests based on the presence of a cookie.
  • We trigger the crash with a request from javascript to a special controller.

Although we can make sure the feature works, we need to better understand the scenarios E2E to make sure there is no situation in which it can have issues where a temporary disconnect gets interpreted as a graceful one.

Metadata

Metadata

Assignees

Labels

DoneThis issue has been fixedarea-blazorIncludes: Blazor, Razor Componentstask

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions