When building web services, we often encounter a difficult problem:When we want to stop the service, how do we ensure that the request being processed can be completed smoothly instead of a sudden interruption?This technology is called "elegant shutdown" and it ensures that all requests are handled properly when the service is shut down.
In this article, we will demonstrate how to use the Gin framework to achieve elegant shutdown in Go with a simple example.
What is elegant shutdown?
Elegant shutdown means that before shutting down the service, the service first handles the request currently being processed, and then shuts down the service. This ensures that the service will not lose the request and will not affect the request being processed. This approach can improve user experience and prevent data loss or inconsistency caused by service disruption. and executeCtrl + C
orkill -2 pid
The command to close the service will not wait for the service to complete the request, which will cause the service to lose the request.
How to achieve elegant shutdown?
After Go version 1.8,Built-in
Shutdown()
The method supports elegant shutdown.
Code implementation
Let's look at a specific code example. Through this example, we will show how to achieve elegant shutdown.
package main import ( "context" "log" "net/http" "os" "os/signal" "syscall" "time" "/gin-gonic/gin" ) func main() { router := () // Define a simple route ("/ping", func(c *) { // Simulate a time-consuming operation, such as a database query or external API call (5 * ) (, { "message": "pong", }) }) // Configure HTTP server srv := &{ Addr: ":8080", Handler: router, } // Start the server go func() { if err := (); err != nil && err != { ("Failed to start server: %v", err) } }() // Wait for the interrupt signal to gracefully shut down the server, setting a 5-second timeout for the shutdown operation quit := make(chan , 1) // Create a channel to receive signals // kill will send a signal by default // kill -2 send signal. Our commonly used `Ctrl+C` is to trigger the system SIGINT signal. // kill -9 sends a signal, but cannot be captured, so it does not need to be added // Forward the received or signal to quit (quit, , ) // It won't block here <-quit // Blocking is here, and the above two signals will be executed only when the above two signals are received. ("Shutdown Server ...") // Create a 5-second timeout context ctx, cancel := ((), 5*) defer cancel() // Elegantly close the service within 5 seconds (process unprocessed requests before closing the service), and exit after more than 5 seconds if err := (ctx); err != nil { ("Server Shutdown: ", err) } ("Server exiting") }
Code parsing
1. Routing definition and service startup
router := () ("/ping", func(c *) { (5 * ) (, { "message": "pong", }) })
First, we created a simple Gin route and defined a/ping
interface. When accessing this interface, the server simulates a 5-second operation and returns a JSON response. This code shows a typical scenario where an elegant shutdown may be required: the server may be processing time-consuming requests, and if it is shut down directly at this time, the request will be interrupted.
2. HTTP server configuration and startup
srv := &{ Addr: ":8080", Handler: router, } go func() { if err := (); err != nil && err != { ("Failed to start server: %v", err) } }()
We useThe structure is configured and started an HTTP server. The server runs in a separate goroutine so that the main program can continue to execute without waiting for the server to start.
3. Capture system signals
quit := make(chan , 1) (quit, , ) <-quit
To achieve elegant shutdown, we need to capture the system signal. Used hereos/signal
Packet to monitorand
Signal. When the user presses
Ctrl+C
Or bykill
When the command sends signals, these signals are captured and sent toquit
The program will then resume from the blocking state and continue to execute subsequent code.
4. Achieve elegant shutdown
ctx, cancel := ((), 5*) defer cancel() if err := (ctx); err != nil { ("Server Shutdown: ", err) }
After capturing the shutdown signal, we useof
Shutdown
Method to achieve elegant shutdown.Shutdown
Method accepts acontext
Parameters, thiscontext
Set a timeout time. Here, we set a 5-second timeout, meaning that the server will wait for the unfinished request to be processed within 5 seconds and then shut down. If the set timeout time is exceeded, the server will exit and the program will end normally.
How to verify the effect of elegant shutdown?
To verify the effect of elegant shutdown, follow these steps:
- Open the terminal and run go run gin_shutdown.go
- Open the browser and access
http://127.0.0.1:8080/ping
At this time, the browser should have a white screen waiting for the server to return a response - Quickly press the Ctrl+C command on the terminal you just opened, and the program will be automatically sent to the
- At this time, the program will not exit immediately, but will wait for the above2The step response is returned and then exited, thus achieving the effect of elegant shutdown
Summarize
Elegant shutdown is an important technical point in building robust web services, which ensures that all requests being processed can be properly completed when the service is closed. In this article, we demonstrate how to achieve elegant shutdown in Go through the Gin framework. In this way, we can improve the user experience and reduce various potential problems caused by service outages.
This is the article about how Go language can achieve elegant shutdown in web services. For more relevant content on elegant Go, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!