文章目录
- 程序安全退出
- 执行代码的基本:信号拦截
- 执行代码的改进:信号拦截包装器
- 实践
- 捕获键盘输入
- 示例代码
- go-svc介绍
程序及服务的控制是指在计算机系统中对程序和服务进行管理、监控和调控的过程。这个过程可以涉及到多个方面,包括资源管理、运行状态监测、安全性控制等。本质上而言就是正确的启动,并可控的停止或退出。在go语言中,其实就是程序安全退出、服务控制两个方面。
程序安全退出
在代码部署后,我们可能因为服务配置发生变化或其他各种原因,需要将服务停止或者重启。通常就是for循环阻塞,运行代码,然后通过control+C或者kill来强制退出。代码如下:
//file svc1.go
package mainimport ("fmt""time"
)
//当接收到Control+c,kill -1,kill -2,kill -9 均无法正常执行defer函数
func main() {fmt.Println("application is begin.")//以下代码不会执行defer fmt.Println("application is end.")for {time.Sleep(time.Second)fmt.Println("application is running.")}
}
但这种情况下,程序是不会执行defer的代码的,因此无法正确处理结束操作,会丢失一些很关键的日志记录、消息通知,非常不安全的。这时,需要引入一个简单的框架,来执行退出。
执行代码的基本:信号拦截
//file svc2.go
package mainimport ("fmt""time""os/signal""os"
)
//当接收到Control+c,kill -1,kill -2 的时候,都可以执行执行defer函数
// kill -9依然不会正常退出。
func main() {fmt.Println("application is begin.")//当程序接受到退出信号的时候,将会执行defer fmt.Println("application is end.")//协程启动的匿名函数,模拟业务代码go func(){for {time.Sleep(time.Second)fmt.Println("application is running.")}}()//捕获程序退出信号msgChan:=make(chan os.Signal,1)signal.Notify(msgChan,os.Interrupt,os.Kill)<-msgChan
}
此时,我们实现了程序退出时的信号拦截,补充业务代码就可以了。但实际业务逻辑至少涉及到初始化、业务处理、退出三大块,代码量多了,会显得比较混乱,这就需要规范代码的结构。
执行代码的改进:信号拦截包装器
考虑上述情况,我们将正常的程序定义为:
Init: 系统初始化,比如识别操作系统、初始化服务发现Consul、Zookeper的agent、数据库连接池等。
Start:程序主要业务逻辑,包括但不限于数据加载、服务注册、具体业务响应。
Stop: 程序退出时的业务,主要包括内存数据存储、服务注销。
改写之前的代码
//file svc3.go
package mainimport ("fmt""time""study1/svc"
)type Program struct {}func (p *Program) Start()error {fmt.Println("application is begin.")//必须非阻塞,因此通过协程封装。go func(){for {time.Sleep(time.Second)fmt.Println("application is running.")}}()return nil
}
func (p *Program)Init()error{