go語言 go-svc包


閱讀 NSQ 源碼時,看到NSQ使用了 go-svc 來啟動nsq的相關程序,使得在程序退出的時候可以做一些釋放資源等收尾工作。
使用起來非常簡單,定義一個Service,實現其 svc.Service中的接口即可。
 
簡單使用:
func main() {
	prg := &program{}
	//運行程序
	if err := svc.Run(prg, syscall.SIGINT, syscall.SIGTERM); err != nil {
		log.Fatal(err)
	}
}
//初始化方法
func (p *program)  Init(env svc.Environment) error {
	fmt.Println("init.....")
	return nil
}
//啟動方法
func (program) Start() error {
	fmt.Println("start.....")
	fmt.Println(syscall.Getpid())
	go func() {
		ticker := time.NewTicker(2 * time.Second)
		for t := range ticker.C {
			fmt.Println("tick at", t)
		}
	}()
	return nil
}
//結束方法
func (program) Stop() error {
	fmt.Println("stop.....")
	

  

注意事項

1.Start方法中不能只直接阻塞,需要在Start方法中新開goroutine去寫需要阻塞的代碼。
2.svc.Run()方法的第二個參數可以指定需要程序監聽的信號,默認情況下不指定的話,默認會監聽 SIGINT和 SIGTERM兩個。根據具體需要進行指定,比如本例中還監聽了SIGUSR1.

實現原理

其實go-svc代碼實現很簡單,使用了標准庫中的os/signalNotify方法。
下面的代碼截取於judwhite/go-svc/svc/svc-other.go:

// Run runs your Service.
//
// Run will block until one of the signals specified in sig is received.
// If sig is empty syscall.SIGINT and syscall.SIGTERM are used by default.
func Run(service Service, sig ...os.Signal) error {
    env := environment{}
    if err := service.Init(env); err != nil {
        return err
    }

    if err := service.Start(); err != nil {
        return err
    }

    if len(sig) == 0 {
        sig = []os.Signal{syscall.SIGINT, syscall.SIGTERM}
    }

    signalChan := make(chan os.Signal, 1)
    signalNotify(signalChan, sig...)
    //signalNotify方法其實就是 signal.Notify 方法
    //var signalNotify = signal.Notify
    <-signalChan

    return service.Stop()
}

  標准庫里面的 os/signal中的 Notfiy方法簽名如下:

func Notify(c chan<- os.Signal, sig ...os.Signal) {}

  其實還有個開源包 endless 也是做類似的事情,大家有興趣可以看看。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM