[Go] 捕捉信号以优雅地关闭服务器进程

在开发服务器相关的程序时,时常需要优雅地(gracefully)关闭服务器进程。这就需要捕捉并处理操作系统对进程产生的信号。

  • 当服务器进程在前台运行时,我们通常用^C结束它,这时,会产生SIGINT信号
  • 当服务器进程在后台运行时,我们通常用kill $pid结束它,这里,会产生SIGTERM信号

以下代码示例在 Golang 中处理信号,并优雅地关闭服务器然后退出:

package main

import (
    "context"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    server := http.Server{}

    // 把服务器放到 goroutine 中去执行
    go func() {
        if err := server.ListenAndServe(); err != nil {
            // 手动调用 Shutdown 时会产生这个错误
            if err != http.ErrServerClosed {
                log.Println(err)
            }
        }
    }()

    log.Printf("server pid: %d\n", os.Getpid())

    // 捕捉指定的信号
    quit := make(chan os.Signal)
    // 前台时,按 ^C 时触发
    signal.Notify(quit, syscall.SIGINT)
    // 后台时,kill 时触发。kill -9 时的信号 SIGKILL 不能捕捉,所以不用添加
    signal.Notify(quit, syscall.SIGTERM)

    // 等待退出信号
    sig := <-quit
    log.Printf("received signal: %v\n", sig)

    // 收到信号后,优雅地关闭服务器
    log.Println("server shutting down")
    if err := server.Shutdown(context.Background()); err != nil {
        log.Println(err)
    }
    log.Println("server shutted down")
}

参考资料

发表于:2019年07月12日 ,阅读量:57 ,标签:HTTP · Go · 信号

版权声明:若非特别注明,本站所有文章均为作者原创,转载请务必注明原文地址。