优雅的在go程序中读取系统信号

之前写了一个Gin项目, 把一些秘钥写在配置文件中, 然后由于aws的策略问题, 这些秘钥需要定期更新, 在之前, 我需要更改完秘钥后, 重新启动程序来读取更改后的key.这样非常不优雅

所以去看了gin的官方文档, 了解一下如何捕获信号然后处理, 现在可以实现给程序发一个HUP 信号, 就让程序读取配置文件而不用重启程序, 非常方便

下面上代码

//创建一个信号管道
	signalChannel := make(chan os.Signal, 1)

	go func() {
		//这个例程启动gin服务, 如果接收到退出信号, 就会调用err != nil后的逻辑,然后延迟关闭管道,让main函数退出
		defer close(signalChannel)
		if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			log.Fatalf("关闭gin服务错误:%v", err)
		}
	}()

	defer func() {
		//延迟关闭redis的连接
		global.R.Close()
		//延迟关闭db的连接
		db, _ := global.DB.DB()
		db.Close()
	}()

	//这里会注册一个监听服,会捕获给定的3个信号量送入到给定的管道
	signal.Notify(signalChannel, syscall.SIGHUP, syscall.SIGTERM, os.Interrupt)

	//循环读取信号管道内的信号,如果是退出信号,调用shutdown函数关闭http服务,关闭管道,退出程序.
	//如果是HUP信号,重读配置文件
	for _sig := range signalChannel {
		switch _sig {
		case syscall.SIGHUP:
			global.Logger.Info("接收到重读配置文件信号,开始重新读取配置文件")
			err := setupSetting()
			if err != nil {
				global.Logger.Fatalf("重读配置文件异常: %v,gin服务将退出", err)
			}
			global.Logger.Info("重新读取配置文件成功")
		case os.Interrupt:
			global.Logger.Infof("接受到interrupt信号,gin服务将退出")
			s.Shutdown(global.Ctx)
		case syscall.SIGTERM:
			global.Logger.Infof("接受到-15信号,gin服务将退出")
			s.Shutdown(global.Ctx)
		default:
			continue
		}
	}
	log.Println("gin服务退出....")

接下来我们就要实现一个功能, 就是让我的systemd服务文件支持reload功能,类似于systemctl reload nginx这样

编辑我们的服务文件, 添加一行

ExecReload=/bin/kill -HUP $MAINPID

然后重载systemd, 进行测试

可以看到成功接收到了信号, 非常的完美


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注