youbbs
youbbs
1437 0 0

Go 应用优雅重启的优雅实现

Go 1.8版本之后, http.Server 内置的 Shutdown() 方法就支持优雅地关机,关键需要监听系统的信号及 context 的处理。

监听中断

signalChan := make(chan os.Signal, 1)

signal.Notify(
	signalChan,
	syscall.SIGHUP,  // kill -SIGHUP XXXX
	syscall.SIGINT,  // kill -SIGINT XXXX or Ctrl+c
	syscall.SIGTERM, // kill -SIGTERM XXXX
	syscall.SIGQUIT, // kill -SIGQUIT XXXX
)

<-signalChan

context 处理

ctx, cancel := context.WithCancel(context.Background())

httpServer := &http.Server{
	Addr:        ":8082",
	Handler:     mux,
	BaseContext: func(_ net.Listener) context.Context { return ctx },
}
httpServer.RegisterOnShutdown(cancel)

完整例子

package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"net/http"
	"os"
	"syscall"
	"time"

    "github.com/vardius/shutdown"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		fmt.Fprintf(w, "Hello!")
	})

	httpServer := &http.Server{
		Addr:    ":8080",
		Handler: mux,
		BaseContext: func(_ net.Listener) context.Context { return ctx },
	}

	stop := func() {
		gracefulCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()

		if err := httpServer.Shutdown(gracefulCtx); err != nil {
			log.Printf("shutdown error: %v\n", err)
		} else {
			log.Printf("gracefully stopped\n")
		}
	}

	// Run server
	go func() {
		if err := httpServer.ListenAndServe(); err != http.ErrServerClosed {
			log.Printf("HTTP server ListenAndServe: %v", err)
			os.Exit(1)
		}
	}()

	shutdown.GracefulStop(stop) // will block until shutdown signal is received
}

参考 https://github.com/vardius/shutdown

0

See Also

Nearby


Discussion

Login Topics