Skip to content

Allow opted-in services to keep accepting during graceful shutdown - #1106

Open
CodyPubNub wants to merge 3 commits into
cloudflare:mainfrom
CodyPubNub:keep-listening-on-terminate
Open

CodyPubNub wants to merge 3 commits into
cloudflare:mainfrom
CodyPubNub:keep-listening-on-terminate

Conversation

@CodyPubNub

Copy link
Copy Markdown
Contributor

Addresses #505

Summary

  • add Service::keep_listening_on_terminate(&Server) behind a default-off keep_listening_on_terminate Cargo feature, exposed by pingora-core, pingora-proxy, and pingora
  • opted-in services continue accepting connections during graceful shutdown after SIGTERM, until runtime shutdown; they still stop accepting on SIGQUIT during a graceful upgrade
  • add documentation, a readiness and metrics example, and regression tests

Motivation

When SIGTERM starts graceful shutdown, listening services stop accepting new connections. Readiness probes and metrics scrapes on new connections are then refused while the process drains, preventing applications from reporting their drain state to those clients.

This opt-in keeps dedicated readiness and metrics services reachable until runtime shutdown, so the application chooses how they respond: keep returning 200, or report draining with a status such as 404 or 5xx. The example tracks draining with a background service's ShutdownWatch and returns 503 while draining.

Readiness and metrics example · API rustdoc and lifecycle caveats

Design

  • Explicit feature gate: unlike set_connection_filter(), which compiles as a no-op without its feature, this method is unavailable when the feature is disabled, so the requested shutdown behavior cannot silently disappear.
  • Subscribe through &Server: the service obtains its execution-phase subscription directly from the server, so callers do not need to supply a receiver or arrange its subscription timing. Because Server::run(self) consumes the server, the method can't be called once it runs.
  • Lifecycle behavior: opted-in listeners remain active until runtime shutdown. ServerApp::cleanup is not called for these services, and an HTTP proxy's Session::is_process_shutting_down() remains false; applications use a separate shutdown notification to report draining. Calling cleanup while they still accept requests could dismantle resources they need.
  • Upgrade behavior: the implementation relies on upgrade phases being published before the shutdown broadcast, including when there are no sockets to send. A real-server regression test covers this ordering.

Cost

  • Disabled: the added state and shutdown handling compile out.
  • Enabled: one Option<Arc<_>> per service, cloned into each endpoint task, plus one check at shutdown; no per-connection or per-request work.

Tests

  • Eight unit tests cover terminate, upgrade, default behavior, phase delivery edge cases, and agreement across concurrent listeners.
  • Two real-server tests verify that opted-in readiness remains available during termination while the default listener closes, and that both listeners close during upgrade. On Linux, upgrade coverage includes FD handoff.
  • Tests use pre-bound sockets to avoid port-rebinding races and assert listener closure as ConnectionRefused.
  • CI lints and tests with the feature enabled and builds the example.

Feature-enabled CI step

- Readiness and metrics endpoints stop answering once SIGTERM closes every
  listener, so orchestrators see a dead process during drain (cloudflare#505)
- Add Service::keep_listening_on_terminate(&Server) behind the default-off
  keep_listening_on_terminate feature (pingora-core, forwarded by
  pingora-proxy and pingora); graceful upgrade still closes the listeners
- Gate the method itself: a no-op when the feature is off would compile and
  still refuse readiness probes on SIGTERM
- Document the SIGTERM/SIGQUIT behavior and add a proxy example with a
  draining readiness endpoint
- Add unit and real-server tests, plus a CI step that lints, tests and builds
  the example with the feature enabled
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

Successfully merging this pull request may close these issues.

1 participant