在Go1.16的更新中,signal包增加了一个函数NotifyContext,可以让我们更优雅的编写服务的优雅重启(GracefulRestart)。服务的优雅重启主要包括两个方面:退出的旧服务需要GracefulShutdown,不强行杀掉进程,不泄露系统资源。依次重启集群中的服务实例,保证服务不中断。第二个问题是关于部署方式的。改天我会写一篇讨论。今天主要讲讲如何优雅退出。首先,在代码中,如果使用外部资源,必须使用defer调用Close()方法关闭。那么我们需要拦截系统的中断信号,保证程序在收到中断信号后有序退出,这样所有的defer都会被执行。以前大概是这样写的:funceverLoop(ctxcontext.Context){LOOP:for{select{case<-ctx.Done()://收到退出无限循环的信号breakLOOPdefault://模拟一个睡眠业务逻辑time.Sleep(time.Second*10)}}}funcmain(){//创建一个可以手动取消的Contextctx,cancel:=context.WithCancel(context.Background())//监听系统信号,只有SIGINT(Ctrl+c),这里监听SIGTERM//在systemd和docker中,都是先发送SIGTERM,过一会才发送SIGKILL,不退出//所以这里没有捕获到SIGKILLsig:=make(chanos.Signal,1)signal.Notify(sig,syscall.SIGINT,syscall.SIGTERM)gofunc(){<-sigcancel()}()//开始无限循环,退出everLoop(ctx)fmt.Println("gracefulshuwdown")}现在多了一个新函数,这一段变得更简单了:funcmain(){//监控系统信号并创建Context现在一步到位ctx,stop:=signal.NotifyContext(context.Background(),syscall.SIGINT,syscall.SIGTERM)//当接收到信号时,会自动触发ctx的Done。这个停止意味着注册的信号不再被捕获,是一种资源的释放。deferstop()//开始无限循环,收到信号就会退出everLoop(ctx)可以轻松实现。使其成为您的服务程序的标准配置。终于在写最新的独立项目LetServerRun的时候发现了这种最新的写法。LetServerRun允许您使用微信公众号作为便携式终端来控制您的服务器。在其Agent的main函数中有上述用法的例子,欢迎参考。附上LetServerRun服务号二维码。感兴趣的同学可以关注一下:
