首先,何为优雅退出?
我们最常见的杀死一个应用程序是通过kill -9 或者在应用程序上执行ctrl+c。
但是程序内部如何结束的我们不得而知, 如果是暴力立刻中断,显然不是我们想要的优雅退出。
说到这,我们就大致清楚了优雅退出需要考虑哪些问题。
- 收到停止请求时,当前正在处理的任务如何处理? 让其正常执行完毕后再优雅退出。
- 收到请求时,后来的任务和请求如何处理? 不处理这些请求任务,等待1中的请求任务处理完毕后退出程序。
下面用一个流程图来说明此问题。
这里主要涉及到2个信号的传递
- 程序接受到终止信号后,告知任务程序停止接受新的请求任务。
- 任务程序运行完毕后,告知主程序优雅退出。
下面通过代码来进行演示
package main
import "fmt"
import "os"
import "time"
import "syscall"
import "os/signal"
var (
stop = false
finish = make(chan bool)
quitSignal = make(chan os.Signal)
)
func main() {
signal.Notify(quitSignal, []os.Signal{syscall.SIGINT, syscall.SIGTERM}...)
go start()
// 收到终止信号后, shutdown
<-quitSignal
close(quitSignal)
shutdown()
fmt.Println("stop")
<-finish
close(finish)
fmt.Println("exit")
}
func start() {
fmt.Println("start")
// 如果收到终止信号,则停止执行任务
for !stop {
fmt.Println("do")
time.Sleep(time.Second)
}
// 任务执行完毕后,通知主协程退出程序
finish <- true
}
func shutdown() {
stop = true
}