Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for graceful shutdown #287

Open
atheriel opened this issue Nov 16, 2020 · 2 comments
Open

Support for graceful shutdown #287

atheriel opened this issue Nov 16, 2020 · 2 comments

Comments

@atheriel
Copy link
Contributor

My motivation here is that to have some sort of graceful transition during Shiny deployments so that existing users don't immediately greyscreen. By this I mean that existing websocket/HTTP connections should continue to work but new connections cannot be made to the running server.

As an external example, the HTTP server from the Go standard library can be put into "shutdown" mode:

Shutdown works by first closing all open listeners, then closing all idle connections, and then waiting indefinitely for connections to return to idle and then shut down.

Which sounds like the right approach to me. Waiting indefinitely is fine for our usecase, since SIGKILL can be used to terminate the process eventually if it exceeds some timeout. (This is how Kubernetes works by default.)

There is an upstream issue on libuv for a direct "stop listening" API that links to various supporting discussions, but it has not been implemented.

The libuv thread above suggests emulating "stop listening" support by having the connections callback just call uv_close() right after calling uv_accept() (as simply not calling uv_accept will accumulate connections in the kernel). I believe httpuv could do when a "shutdown" flag has been set on the server object, although I'm not sure how this ought to be exposed at the R level.

This is mildly related to #226.

@jcheng5
Copy link
Member

jcheng5 commented Nov 17, 2020

I don't know if this can work perfectly for Shiny; while most communication happens over the websocket, some features require HTTP requests to be issued (among the most commonly used are downloadButton, DT tables, server-side selectize). So regular reactivity would continue to work, but then these features would time out.

Shiny Server knows how to gracefully transition between two versions of an app under its purview, but the fact that you mentioned Kubernetes makes me think it's important for you to do deployments at the container level?

@atheriel
Copy link
Contributor Author

some features require HTTP requests to be issued

Yeah, that's the issue we've run into. I was assuming HTTP keep-alive would keep these connections open, but perhaps that is not the case, which might torpedo this idea.

And yes, we'd ideally like to use Kubernetes-native features instead of Shiny Server, if possible. How exactly does Shiny Server perform this graceful transition (or should I just read the source)? Could it be recreated without running that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants