go笔记 NSQ (2) (从NSQ启动入口看go如何用svc的管理应用的生命周期)

通过查看nsqd.go的主应用入口,会发现其使用了svc来管理应用的生命周期。

func main() {
    prg := &program{}
    if err := svc.Run(prg, syscall.SIGINT, syscall.SIGTERM); err != nil {
        log.Fatal(err)
    }
}

可以看到svc参数主要有两部分,第一个是svc.Service接口 即管理生命周期的接口,另一个是signal的不定长参数  也就是响应的信号。而这个program则是nsq自己实现svc.Service接口的结构体。我们可以看下这个接口

type Service interface {
    //可添加一些应用初始化时的操作
    Init(Environment) error

    //应用启动操作,但注意不能在这儿阻塞
    Start() error

    //应用被停止时的操作
    Stop() error
}

里面主要包含了应用的一些生命周期的操作,包括初始化,启动,以及销毁方法。具体的我们可以写一个案例来说明

 

svc案例

 

  引入依赖,对于的go.mod文件如下

module application

go 1.14

require (
    github.com/judwhite/go-svc v1.1.2
    golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 // indirect
)

  编写对应的应用程序

package main

import (
    "github.com/judwhite/go-svc/svc"
    "log"
    "os"
    "syscall"
    "time"
)

type pro struct {

}

func main()  {

    pro :=&pro{}

    svc.Run(pro,syscall.SIGINT)


}

func (p *pro)Init( e svc.Environment) error{
    port := os.Getpid()
    log.Printf("程序已经初始化 端口为%d  \n",port)
    return nil

}

func (p *pro)Start() error{
    log.Printf("程序已经start\n")
    go func() {
        tik := time.NewTicker(3*time.Second)
        for  {
            c := <-tik.C
            log.Printf("当前时间为:%s \n",c.Format("2006-01-02 15:04:05"))
        }

    }()
    return nil
}

func (p *pro)Stop() error{
    log.Printf("程序已经stop\n")
    return nil
}

 

  可以看到我们在Init方法中可以获取到例如程序的pid等信息,在Start方法中运行应用,在Stop方法中则可以监听信号,例如中断(SIGINT)等。运行程序可以在控制台看到对应的生命周期信息,使用例如Ctrl+c程序便可以监听到中断信息而做出响应,运行后效果如下

 

 

 可以看到对于管理应用的生命周期还是很方便的。

 

当然svc之所以最终能够监视到信号信息还是依赖go的signal包下的Notify方法,我们可以写一个demo来看一下go中signal的Notify方法如何使用

package main

import (
    "fmt"
    "log"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {

    sin := make(chan os.Signal, 1)
    fmt.Printf("系统启动pid为: %d \n",os.Getpid())
    signal.Notify(sin,syscall.SIGINT,syscall.SIGKILL,syscall.SIGTERM)
    go func() {
        tik := time.NewTicker(3*time.Second)
        for  {
            <-tik.C
            log.Printf("主业务执行中。。。\n")
        }

    }()
    <-sin
    fmt.Println("系统关闭")
}

 

 

  本方法系统启动后会一直阻塞,直到监听到信号监听列表里面的信号后会向我们创建的chan里边放入一条信息,而这个时候阻塞的chan则会执行后面的逻辑

 

   实现了一个简易版的svc

 

  当然了 ,总结下来实现逻辑很简单,就是利用了go的信号监听和chan的通信便利性来实现的一个解耦的应用生命周期管理工具,将应用的初始化,启动,销毁独立开来。

 

  

posted @ 2020-05-28 17:14  雨落寒沙  阅读(329)  评论(0编辑  收藏  举报