mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-16 13:22:09 +08:00
feat(gracefulstop): add wrapper Shutdown
We start httpServer by gin as example below In my project. Here is a case: 1. Start gin http server 2. Receive data from gin http server and send task to worker to process. 3. The worker stop at first when my process go to exit. But my gin http server is running, some error happened. We expect to stop gin http server at first by calling func 'http.Server.Shutdown(context.TODO())' to avoid process error. So, can i make a mr and add wrapper func 'Shutdown()' to gin for graceful stop my process. Here are my use case. ```golang func main() { // Set up a http server. r := gin.Default() // ... go func() { // Run http server if err := r.Run(":8899"); err != nil { log.Fatalf("could not run server: %v", err) } }() // Run worker go RunWorker() // wait signal to stop WaitSignal() } // RunWorker run worker in one goroutine func RunWorker() { for !isStop { // ... some request received by gin http server ... // ... do some work ... } } // WaitSignal stop signal handle func WaitSignal() { shutdownHook := make(chan os.Signal, 1) signal.Notify(shutdownHook, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, os.Interrupt) <-shutdownHook GracefulStop() // wait 2 second for graceful stop. time.Sleep(2 * time.Second) os.Exit(0) } // GracefulStop graceful stop http.Server at first, then stop all workers. func GracefulStop() { // 1. stop http.Server and refuse new data are received. err := server.Shutdown(context.TODO()) // 2. stop worker and finish tasks in process. // StopWorker() ... } ```
This commit is contained in:
parent
05caa5c00e
commit
8d09dce3c2
35
gin.go
35
gin.go
@ -5,6 +5,7 @@
|
||||
package gin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net"
|
||||
@ -164,6 +165,9 @@ type Engine struct {
|
||||
maxSections uint16
|
||||
trustedProxies []string
|
||||
trustedCIDRs []*net.IPNet
|
||||
|
||||
// http.Server list for graceful Shutdown
|
||||
serverList []*http.Server
|
||||
}
|
||||
|
||||
var _ IRouter = &Engine{}
|
||||
@ -379,7 +383,9 @@ func (engine *Engine) Run(addr ...string) (err error) {
|
||||
|
||||
address := resolveAddress(addr)
|
||||
debugPrint("Listening and serving HTTP on %s\n", address)
|
||||
err = http.ListenAndServe(address, engine.Handler())
|
||||
server := &http.Server{Addr: address, Handler: engine.Handler()}
|
||||
engine.serverList = append(engine.serverList, server)
|
||||
err = server.ListenAndServe()
|
||||
return
|
||||
}
|
||||
|
||||
@ -498,7 +504,9 @@ func (engine *Engine) RunTLS(addr, certFile, keyFile string) (err error) {
|
||||
"Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
|
||||
}
|
||||
|
||||
err = http.ListenAndServeTLS(addr, certFile, keyFile, engine.Handler())
|
||||
server := &http.Server{Addr: addr, Handler: engine.Handler()}
|
||||
engine.serverList = append(engine.serverList, server)
|
||||
err = server.ListenAndServeTLS(certFile, keyFile)
|
||||
return
|
||||
}
|
||||
|
||||
@ -521,7 +529,9 @@ func (engine *Engine) RunUnix(file string) (err error) {
|
||||
defer listener.Close()
|
||||
defer os.Remove(file)
|
||||
|
||||
err = http.Serve(listener, engine.Handler())
|
||||
server := &http.Server{Handler: engine.Handler()}
|
||||
engine.serverList = append(engine.serverList, server)
|
||||
err = server.Serve(listener)
|
||||
return
|
||||
}
|
||||
|
||||
@ -558,7 +568,9 @@ func (engine *Engine) RunListener(listener net.Listener) (err error) {
|
||||
"Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.")
|
||||
}
|
||||
|
||||
err = http.Serve(listener, engine.Handler())
|
||||
server := &http.Server{Handler: engine.Handler()}
|
||||
engine.serverList = append(engine.serverList, server)
|
||||
err = server.Serve(listener)
|
||||
return
|
||||
}
|
||||
|
||||
@ -585,6 +597,21 @@ func (engine *Engine) HandleContext(c *Context) {
|
||||
c.index = oldIndexValue
|
||||
}
|
||||
|
||||
// Shutdown is Wrapper for http.Server.Shutdown(ctx)
|
||||
// Once Shutdown has been called on a server, it may not be reused;
|
||||
// future calls to methods such as Serve will return ErrServerClosed.
|
||||
func (engine *Engine) Shutdown(ctx context.Context) error {
|
||||
for _, srv := range engine.serverList {
|
||||
if srv == nil {
|
||||
continue
|
||||
}
|
||||
if err := srv.Shutdown(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (engine *Engine) handleHTTPRequest(c *Context) {
|
||||
httpMethod := c.Request.Method
|
||||
rPath := c.Request.URL.Path
|
||||
|
Loading…
x
Reference in New Issue
Block a user