Hone logo
Hone
Problems

Graceful Shutdown in a Go HTTP Server

Graceful shutdown is crucial for production applications to avoid data loss and ensure a smooth user experience. This challenge asks you to implement a Go HTTP server that gracefully handles shutdown signals (SIGINT and SIGTERM), allowing it to finish processing in-flight requests before exiting. This is vital for preventing incomplete transactions and ensuring data consistency.

Problem Description

You are tasked with creating a simple HTTP server that listens on port 8080 and responds with "Hello, World!". The server must gracefully shut down when it receives either a SIGINT (Ctrl+C) or SIGTERM signal. Graceful shutdown means the server should:

  1. Stop accepting new connections.
  2. Wait for all currently in-flight requests to complete.
  3. Close any open connections.
  4. Exit cleanly.

To simulate in-flight requests, the server will include a delay of 2 seconds in its handler. This allows you to observe the graceful shutdown behavior while requests are still being processed.

Key Requirements:

  • Use the net/http package for creating the HTTP server.
  • Use the context package for managing request contexts and timeouts.
  • Use the os and signal packages to listen for SIGINT and SIGTERM signals.
  • Implement a Shutdown function that handles the shutdown process.
  • The server should log messages indicating when it starts, stops accepting new connections, and shuts down completely.

Expected Behavior:

When the server is running, sending a SIGINT or SIGTERM signal should trigger the graceful shutdown sequence. The server should continue to serve existing requests until they complete (after a 2-second delay), then log a shutdown message and exit. New requests received after the signal is sent should not be processed.

Edge Cases to Consider:

  • What happens if a request takes longer than the timeout to complete? (While not explicitly required, consider how your solution might handle this).
  • How does the server handle multiple signals received in quick succession?
  • What happens if the server is already shutting down when another signal is received?

Examples

Example 1:

Input: Server running, send SIGINT (Ctrl+C)
Output:
- Server logs: "Server started on :8080"
- Server logs: "Shutting down..."
- Server logs: "Server stopped accepting new connections"
- After 2 seconds (simulated request processing time): Server logs: "Server shutting down"
- Server exits cleanly.

Example 2:

Input: Server running, send SIGTERM
Output:
- Server logs: "Server started on :8080"
- Server logs: "Shutting down..."
- Server logs: "Server stopped accepting new connections"
- After 2 seconds (simulated request processing time): Server logs: "Server shutting down"
- Server exits cleanly.

Example 3: (Multiple Signals)

Input: Server running, send SIGINT, then immediately send SIGTERM
Output:
- Server logs: "Server started on :8080"
- Server logs: "Shutting down..."
- Server logs: "Server stopped accepting new connections"
- After 2 seconds (simulated request processing time): Server logs: "Server shutting down"
- Server exits cleanly. (The second signal should not interrupt the first shutdown sequence)

Constraints

  • The server must listen on port 8080.
  • The request handler must include a 2-second delay.
  • The shutdown process must complete within a reasonable timeframe (e.g., 5 seconds). While not strictly enforced, excessively long shutdown times are undesirable.
  • The code should be well-structured and readable.
  • Error handling should be present, but concise. Focus on the graceful shutdown logic.

Notes

  • Consider using a context.Context with a timeout to manage the lifetime of requests.
  • The http.Server type provides methods for graceful shutdown. Explore these methods.
  • Think about how to signal to the server that it should stop accepting new connections.
  • The goal is to demonstrate a robust and reliable shutdown mechanism, not to build a fully featured HTTP server. Keep the code focused on the core shutdown functionality.
Loading editor...
go