• 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  
    ",port)
        return nil
    
    }
    
    func (p *pro)Start() error{
        log.Printf("程序已经start
    ")
        go func() {
            tik := time.NewTicker(3*time.Second)
            for  {
                c := <-tik.C
                log.Printf("当前时间为:%s 
    ",c.Format("2006-01-02 15:04:05"))
            }
    
        }()
        return nil
    }
    
    func (p *pro)Stop() error{
        log.Printf("程序已经stop
    ")
        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 
    ",os.Getpid())
        signal.Notify(sin,syscall.SIGINT,syscall.SIGKILL,syscall.SIGTERM)
        go func() {
            tik := time.NewTicker(3*time.Second)
            for  {
                <-tik.C
                log.Printf("主业务执行中。。。
    ")
            }
    
        }()
        <-sin
        fmt.Println("系统关闭")
    }

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

       实现了一个简易版的svc

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

      

  • 相关阅读:
    java8知识总结_2.方法引用
    Shell三剑客_1.grep
    java8知识总结_1.Lambda表达式
    javascript中的设计模式
    javascript入门学习
    css3新特性
    Html5新增了什么
    什么是Node.js
    vue项目搭建
    Git使用
  • 原文地址:https://www.cnblogs.com/hetutu-5238/p/12982123.html
Copyright © 2020-2023  润新知