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

NIOHTTP2Handler should handle ChannelShouldQuiesceEvent #336

Open
fabianfett opened this issue Apr 11, 2022 · 2 comments
Open

NIOHTTP2Handler should handle ChannelShouldQuiesceEvent #336

fabianfett opened this issue Apr 11, 2022 · 2 comments

Comments

@fabianfett
Copy link
Member

SwiftNIOExtras offers a QuiescingHelper to gracefully shutdown servers. NIOHTTP2Handler should support shutting down a server connection, when the QuiescingHelper sends out a ChannelShouldQuiesceEvent:

  • Once NIOHTTP2Handler receives a ChannelShouldQuiesceEvent a GoAway frame should be send to the client and new incoming streams should be rejected.
  • Once all previously open streams have finished the connection should be closed.

In NIOHTTP1 the ChannelShouldQuiesceEvent support is implemented in HTTPServerPipelineHandler

@lmcd
Copy link

lmcd commented May 26, 2022

Hmm maybe this is why I was having issues performing a soft-restart of a HTTP/2 Vapor server.
I remember seeing quiesce/shutdown errors.

@glbrntt
Copy link
Contributor

glbrntt commented Jul 26, 2024

  • Once NIOHTTP2Handler receives a ChannelShouldQuiesceEvent a GoAway frame should be send to the client and new incoming streams should be rejected.
  • Once all previously open streams have finished the connection should be closed.

This needs to be handled carefully, the server should attempt to allow for 'in-flight' streams to be opened before it begins to reject streams. It can do this by sending a GOAWAY frame with lastStreamID set to .max followed immediately by a PING. On receiving the PING ACK – and thereby knowing the client received the previous GOAWAY frame – the server can send another GOAWAY frame with a lower lastStreamID, and then begin rejecting streams.

The client may for some reason not send a PING ACK which could leave the server waiting indefinitely. As the library doesn't (currently) have a built-in mechanism to retrieve RTT the server should also set a timer as a fallback mechanism.


In gRPC Swift this is managed by a separate channel handler with a number of different behaviours, many of which are applicable to http servers in general. These include:

  • Closing idle connections (where 'idle' means there are no open streams) after a period of inactivity
  • Using pings to detect broken connections (typically done when connections have open but infrequently used streams)
  • Limiting the maximum age of a connection
  • Limiting how long a graceful shutdown can take

As these are generally useful it may make sense to fold these behaviours (along with the graceful shutdown) either into the NIOHTTP2Handler or into a separate channel handler within swift-nio-http2.

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

3 participants