优雅的结束golang程序

优雅的结束golang程序

实现方式

使用sync.WaitGroup配合context.WithCancel即可优雅的关掉

	ctx, cancel := context.WithCancel(context.Background())
	var wg sync.WaitGroup
	signChan := make(chan os.Signal)
    signal.Notify(signChan, syscall.SIGINT) // ctrl+c
	signal.Notify(signChan, syscall.SIGTERM) // kill

    go func() {
        force := false
        for {
            oscall := <-signChan
            if force {
                os.Exit(1)
            }
            log.Infof("receive system call: %v", oscall)
            cancel()
            force = true
            log.Info("press ctrl+c again to force exit")
        }
    }()
	tasks := make([]func(), 0)
	tasks = append(tasks, func() {
	    someCtx := ....
	    someChan := ....
	    for {
	        select {
	        case a := <- someChan:
	            handle(a)
	        case <-someCtx.Done():
	            return
	        case <-ctx.Done():
	            return
	        }
	    }
	    defer wg.Done()	
    })
    tasks = append(tasks, func() {
        for {
            // 模拟执行了其他耗时操作
            time.Sleep(10 * time.Second)
            if ctx.Err() != nil {
                // cancel() called
                return
            }
        }
    })
    // ... add more task
	wg.Add(len(tasks))
	for _, f := range tasks {
        go f()
    }
    log.Info("running")
    wg.Wait()
    log.Info("shutdown")

代码里我们首先监听 SIGINT 和 SIGTERM, 当程序收到系统信号后调用cancel()通知子task该停止工作了。这里我们
增加了一个force变量,保证可以通过两次ctrl+c命令强行终止程序。

其中 SIGINT 响应ctrl+c命令。SIGTERM 响应系统kill命令(docker stop就是发送此signal)

注意事项

如何正常响应docker stop

有时候会发现运行在docker中的go程序无法正确响应系统信号, 查看docker文档中提到了,docker stop会执行如下操作
The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL.
注意这里提到了 main process,对于docker容器来说就是向pid为1的进程。很多时候我们的container command命令中运行的是一个脚本文件,类似
sh /app/start.sh,文件内容类似如下

echo "start app"
/app/web

这样的脚本执行结果就是 main process 是sh /app/start.sh,而不是我们的/app/web程序,此时要做的就是使用exec命令运行我们的程序

echo "start app"
exec /app/web

这样我们的/app/web就是pid为1的进程了,也就可以正常的收到SIGTERM系统信号

原文地址:https://www.cnblogs.com/zihuyishi/p/14633528.html