apps/nsqlookupd/nsqlookupd.go
nsqlookupd 是一个独立的程序,所以放到 apps 目录下,依赖内部包 nsqlookupd, util,外部包:
# TOML是一种配置文件规范,此包是golang的解析包
# 把命令行和配置文件参数注入到struct中的工具包,只有一个文件
关键代码解析
1、全局变量定义
go 中命令行参数成为 flag,flag 的集合成为 FlagSet,解析命令行参数之前需要先创建 FlagSet,定义每一个 flag,如下面的全局变量所示,同时提供了重要的默认值
var (
flagSet = flag.NewFlagSet("nsqlookupd", flag.ExitOnError)
config = flagSet.String("config", "", "path to config file")
///
)
2、命令行参数解析
flagSet.Parse(os.Args[1:])
os.Args 是所有的命令行参数;os.Args[0] 是执行程序的全路径名;
flagSet.Parse 解析命令行参数,覆盖 flagSet 中的 flag 默认定义
3、nsqlookupd 进程退出方式
定义了两个 chan,signalChan 接收OS发送的退出信号,匿名协程收到数据时,往 exitChan 发送一个 1,此时等待在 exitChan 上的主协程调用 nsqlookupd 的 Exit 方法
signalChan := make(chan os.Signal, 1)
exitChan := make(chan int)
go func() {
<-signalChan
exitChan <- 1
}()
// 告诉 golang 运行时,收到的退出,中断信号传递给 signalChan 通道
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
<-exitChan // 等待退出信号
daemon.Exit()
总结:这种退出方式比较优雅,能够在退出之前做些收尾工作,清理任务和垃圾
4、读取配置文件
var cfg map[string]interface{}
_, err := toml.DecodeFile(*config, &cfg)
详细的 toml 使用文档,参考 toml 的 github
5、创建 nsqlookupd 配置选项的结构体 nsqlookupdOptions
opts := nsqlookupd.NewNSQLookupdOptions()
6、解析命令行参数 flagSet 和 配置文件参数 cfg 到 opts 中
options.Resolve(opts, flagSet, cfg) // 使用了 库
解析时,会查找 opts 定义的 flag tag;优先使用命令行参数,配置文件次之。
7、创建 nsqlookupd 的结构体 NSQLookupd,包含有所有的必要信息,命令行参数 和 默认值
daemon := nsqlookupd.NewNSQLookupd(opts)
8、启动 nsqlookupd
daemon.Main()