Skip to content

http2: add session tracking and graceful server shutdown of http2 server#57586

Closed
pandeykushagra51 wants to merge 7 commits intonodejs:mainfrom
pandeykushagra51:http2/fix-server-close
Closed

http2: add session tracking and graceful server shutdown of http2 server#57586
pandeykushagra51 wants to merge 7 commits intonodejs:mainfrom
pandeykushagra51:http2/fix-server-close

Conversation

@pandeykushagra51
Copy link
Copy Markdown
Contributor

@pandeykushagra51 pandeykushagra51 commented Mar 21, 2025

This change adds proper tracking of HTTP/2 server sessions to ensure they are gracefully closed when the server is shut down. It implements:

  • A new kSessions symbol for tracking active sessions
  • Adding/removing sessions from a SafeSet in the server
  • A closeAllSessions helper function to properly close all active sessions
  • Updates to Http2Server and Http2SecureServer close methods

Breaking Change: any client trying to create new requests on existing connections will not be able to do so once server close is initiated

Fixes: #57611
Refs: https://datatracker.ietf.org/doc/html/rfc7540#section-9.1
Refs: https://nodejs.org/api/http.html#serverclosecallback

More Details:

Purpose

This PR implements proper tracking and graceful shutdown of HTTP/2 sessions when a server is closed. It addresses the gap between the documented behavior of server.close() and its actual implementation for HTTP/2 servers. Also if server have fired close, we should allow it to close as early as possible to free up system resources quickly. This change ensure that once server wants to close, goaway frame will be sent to every open session(connection) so that client get to know that server started shutdown process and client should not send any new request on existing connection.

Current Issues

  • Currently, HTTP/2 servers are at the mercy of clients to close connections.
  • There is no mechanism to notify clients that the server wants to shut down.
  • Misbehaving/Non-compliant clients can keep connections open indefinitely, preventing proper server shutdown.
  • Clients can continue to initiate new requests on existing connections even when the server is trying to close.
  • Start of server shutdown can starve indefinitely, leading to processes that cannot terminate cleanly and causing resource leaks.

Implementation Details

  • Added a kSessions symbol and SafeSet to track active HTTP/2 sessions.
  • Implemented session registration when sessions are created.
  • Created a closeAllSessions helper function to initiate graceful shutdown of all tracked sessions
  • Updated Http2Server and Http2SecureServer close methods to use this functionality

Behavior Clarification

According to the Node.js documentation for server.close():

server.close stops the server from accepting new connections and closes all connections connected to this server which are not sending a request or waiting for a response.

This PR ensures that HTTP/2 servers follow this behavior by:
Closing existing HTTP/2 sessions gracefully, which means:

  • When session.close() is called, a GOAWAY frame is sent to notify clients that the server wants to close the session
  • No new streams (requests) can be initiated on existing connections
  • Existing streams can continue writing/reading data until completion
  • In-flight requests will be allowed to complete
  • Sessions will be terminated after all active streams complete

This implementation aligns with the HTTP/2 protocol specification for connection management as described in RFC 7540 Section 9.1.

API Impact

This is technically a breaking change, as clients attempting to create new requests on existing HTTP/2 connections will be unable to do so once server.close() is called. However, this behavior now correctly matches the documented behavior for HTTP servers.

Testing

This PR includes tests to verify that HTTP/2 sessions are properly tracked and gracefully shut down when the server is closed.

Newly added test files:

  • test-http2-request-after-server-close.js: Verifies that after server.close() is called, clients cannot initiate new requests while existing requests are allowed to complete. Confirms the server properly terminates once all connections are closed.
  • test-http2-server-close-client-behavior.js: Validates that idle connections are immediately closed when server.close() is called, while connections with active streams continue processing until completion. Ensures the server terminates after all connections are properly closed.

Modified test files:

  • test-http2-compat-serverresponse-statusmessage-property-set.js: After server close behavior is updated, this test started to fail. The failure happened because the request from client is under pendingAck state so the session is not yet initiated, as server close is fired during this time and hence client didn't received response which leads to test failure. Now the test is updated to fire server close once the request is complete. As this unit test, test that client should receive http2 status message response, so it is good to close the server only after the request/response cycle is completed. This line tells that pending stream will be cancelled once session close is emitted.
  • test-http2-compat-serverresponse-statusmessage-property.js: Same as above.
  • test-http2-capture-rejection.js: Server close should be fired after server have sent push promise frame.

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author ready PRs that have at least one approval, no pending requests for changes, and a CI started. commit-queue-failed An error occurred while landing this pull request using GitHub Actions. http2 Issues or PRs related to the http2 subsystem. needs-ci PRs that need a full CI run. semver-major PRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

http2 server wait infinitely to close

7 participants