Aspnetcore: Server-side: handle reconnection to different server

Created on 28 Jul 2018  路  8Comments  路  Source: dotnet/aspnetcore

If after a delay, or a lost network connection the websocket disconnects. It seems it will never reconnect.

image

Design affected-few area-blazor c enhancement severity-blocking

Most helpful comment

Note that the expected solution for this is going to involve the app developer making their per-user state serializable so that it's transferrable between servers and doesn't have to be kept live in the server's memory forever. When a user disconnects, we don't know if that's because they are finished, or if it's because there was a network issue and they will attempt to reconnect and resume shortly. So the server doesn't know to keep their state in memory, and even if it does, that wouldn't guarantee the user reconnects to the same server.

In summary, a robust solution will involve the app developer doing some work and accounting for it in their app architecture. We intend to provide patterns to make this straightforward and robust, but it will still require the app developer to be aware of them and fit in with those patterns.

All 8 comments

Yes, this is correct. In fact there are a wide range of cases where recovery behavior is needed (e.g., server goes down and user needs to be transferred to a different server within the load balancing group).

We've been considering these scenarios in detail. However I don't think we have a tracking issue for them yet, so I'm going to change the issue title for this one and use it as the tracking issue.

Note that the expected solution for this is going to involve the app developer making their per-user state serializable so that it's transferrable between servers and doesn't have to be kept live in the server's memory forever. When a user disconnects, we don't know if that's because they are finished, or if it's because there was a network issue and they will attempt to reconnect and resume shortly. So the server doesn't know to keep their state in memory, and even if it does, that wouldn't guarantee the user reconnects to the same server.

In summary, a robust solution will involve the app developer doing some work and accounting for it in their app architecture. We intend to provide patterns to make this straightforward and robust, but it will still require the app developer to be aware of them and fit in with those patterns.

Our company would use server side Blazor for some of our internal tools if there was even simple reconnect support. That would only supports single server and keeping state in memory with timeout.

Assuming that something similar to what is detailed below has already been drafted by the Blazor team internally, this is being submitted here just it in case it helps gets any extra thoughts moving about how the structure of a session control system could work.

Essentially, I am proposing that a new API be created called Session, containing static methods for terminating, resetting, transferring, temporarily (based on a predicate and an auxiliary timeout value) extending the timeout for, or restarting a session. It should also contain a property for the current session, as well as a configuration struct for settings regarding the session's timeout and disconnection settings, providing a settable default instance as well. Session should also have instance events for disconnection, timeout, and reconnection, as well as a settable state object that could be used for identification and data serialization upon disconnection or whenever.

It could also be structured similarly to IJSInterop, with ISession and an implementation called ServerSideBlazorSession or something.

Hope I could provide something useful.

Perhaps I missed it, but is there at least a way to show the user, that he is disconnected from the server? Perhaps with the possibility to reload the page (with loosing the state)?

@Brunni we covered some of what you asked for as part of https://github.com/aspnet/AspNetCore/issues/7537

Since #8177 has been closed and this issue is now in the backlog, if I want to start using Blazor, how should I prepare for this feature when it will be available? Because if the user state needs to be serializable, this must be a key decision during initial application design.

My concern is that if I implement blazor right now, when this issue gets fixed it will be implemented in a way that is incompatible with whatever I came up with. How should one proceed? Load balancing is a very critical scenario for any decent sized application, so it's my primary concern

An IDistributedCache implementation makes state-persistence a fairly trivial problem to solve, as long as the application is designed for it up front. In our case, we set up a request-scoped abstract class keyed on a user identifier (OIDC subject ID, since we have no anonymous-access users), then the apps derive from this to manage various bits of app-specific <TState> data (high-level, like navigation location), which is restored upon the initial connection (driven by persistent OIDC login, but any cookie-stored unique ID would work -- check it in an OnGet for _Host where you still have HttpContext and go from there). Caching is handled automatically by that base class.

Business-level data is persisted directly to the IDistributedCache (optionally DPAPI-protected) instead of being stored in <TState>. We have a rule that no sensitive data can be persisted as app state which eliminates encryption overhead.

We're hoping this type of implementation will make it easier to switch to whatever solution eventually becomes the official answer. Of course, having access to the Blazor client internals would allow such a system to explicitly identify "reconnect" versus "quit and restart" restoration behavior, but we apply an arbitrary expiration policy (ex. 5 minutes) to the startup state-restoration decision.

I like most of the ideas from @TheFanatr but I'd rather see a new API have a name other than Session simply because ASP.NET session-state has such a long history of being discouraged for many good reasons, whereas any non-trivial Blazor SS app virtually _requires_ this for entirely different reasons unrelated to session-style convenience.

Was this page helpful?
0 / 5 - 0 ratings