美文网首页
【Go】优雅上下线(一)

【Go】优雅上下线(一)

作者: 如雨随行2020 | 来源:发表于2022-04-19 02:10 被阅读0次

    @[toc]

    说明

    当你有一个运行在服务器上的程序需要停止时,因为要保持数据的一致性,不能直接杀死程序(kill -9),而是需要做一些“善后”处理,一般来说就是把当前处理的任务完成,这往往涉及多个协程之间协作(后续会展开)。

    那应该怎么处理这种情况呢?我们注意到,在关闭程序(并非kill9强制杀死程序)时,Go可以收到Unix信号,一般来说是两个syscall.SIGINT, syscall.SIGTERM,pm2发送SIGINT(2),k8s发送SIGTERM(15)。

    依据这个,我们可以在程序开始的时候加个监控协程,监听Unix信号,维护一个通道,当收到关闭信号时,将通道关闭,子协程就可以根据通道状态来做到处理完当前任务退出,而不是继续处理下一个

    代码

    // 监听关闭信号(pm2发送SIGINT,k8s发送SIGTERM),然后关闭stop协程
    // 程序可以调用Closed来获取stop的状态
    // 也可以通过GetStopChan来拿到stop,自己监听
    // Once.Do保证MonitorStop只会被调用一次
    
    var stop = make(chan struct{}) //优雅关闭程序标志
    var once = sync.Once{}
    
    func MonitorStop() {
        once.Do(func() {
            // 收到pm2或者k8s的Signal后,设置stop为true,处理完当前的历史课堂后,程序结束
            signals := make(chan os.Signal, 1)
    
            signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
    
            sig := <-signals
            fmt.Printf("process will stop gracefully for sig[%d]\n", sig)
            close(stop)
        })
    }
    
    func Closed() bool {
        select {
        case <-stop:
            return true
        default:
            return false
        }
    }
    
    func GetStopChan() <-chan struct{} {
        return stop
    }
    
    

    相关文章

      网友评论

          本文标题:【Go】优雅上下线(一)

          本文链接:https://www.haomeiwen.com/subject/aisraltx.html