Graceful Shutdown

Graceful shutdown refers to the process where, when a server is being shut down, it does not immediately terminate all connections. Instead, it first stops accepting new requests while allowing existing requests sufficient time to complete their processing before closing the service. This approach prevents requests from being abruptly interrupted, thereby improving user experience and system reliability.

Salvo provides support for graceful shutdown through the handle method of the Server, which retrieves the server handle, followed by calling the stop_graceful method to implement the shutdown. After invoking this method, the server will:

  • Stop accepting new connection requests
  • Wait for existing requests to complete processing
  • Forcefully close any remaining connections after a specified timeout (if provided)

Here is a simple example:

use salvo_core::prelude::*;

#[tokio::main]
async fn main() {
    let acceptor = TcpListener::new("127.0.0.1:5800").bind().await;
    let server = Server::new(acceptor);
    let handle = server.handle();

    // Gracefully shut down the server
    tokio::spawn(async move {
        tokio::time::sleep(std::time::Duration::from_secs(60)).await;
        handle.stop_graceful(None);
    });
    server.serve(Router::new()).await;
}

In the example above:

  • server.handle() retrieves the server handle, which can be used to control the server's lifecycle
  • handle.stop_graceful(None) initiates the graceful shutdown process, where None indicates no timeout is set, meaning the server will wait indefinitely for all requests to complete
  • To set a timeout, you can pass Some(Duration), after which any remaining connections will be forcefully closed

This approach is particularly suitable for applications deployed in container environments or on cloud platforms, as well as for scenarios requiring hot updates to ensure that requests are not unexpectedly interrupted.