代码入口:cmd/prometheus/main.go
命令行参数解析工具:kingpin ,package:gopkg.in/alecthomas/kingpin.v2 , github:https://github.com/alecthomas/kingpin
命令行参数中有部分日期字段是输入类似1m,2h,3y之类,对应的字段类型为:model.Duration,该类型实现了kingpin的Set方法,在kingpin解析的时候自动调用该方法完成2y到go的time.Duration的转换
type Duration time.Duration
// Set implements pflag/flag.Value
func (d *Duration) Set(s string) error {
var err error
*d, err = ParseDuration(s)
return err
}
依次初始化
localStorage = &tsdb.ReadyStorage{}
remoteStorage = remote.NewStorage(log.With(logger, "component", "remote"), localStorage.StartTime)
fanoutStorage = storage.NewFanout(logger, localStorage, remoteStorage)
notifier = notifier.New(&cfg.notifier, log.With(logger, "component", "notifier"))
targetManager = retrieval.NewTargetManager(fanoutStorage, log.With(logger, "component", "target manager"))
queryEngine = promql.NewEngine(fanoutStorage, &cfg.queryEngine)
ctx, cancelCtx = context.WithCancel(context.Background())
ruleManager := rules.NewManager(&rules.ManagerOptions{
Appendable: fanoutStorage,
Notifier: notifier,
QueryEngine: queryEngine,
Context: ctx,
ExternalURL: cfg.web.ExternalURL,
Logger: log.With(logger, "component", "rule manager"),
})
webHandler := web.New(log.With(logger, "component", "web"), &cfg.web)
reloadables := []Reloadable{
remoteStorage,
targetManager,
ruleManager,
webHandler,
notifier,
}
...
reloadConfig(cfg.configFile, logger, reloadables...); //加载配置
...
webHandler.Ready() //至此,初始化完成
模块启动
tsdb.Open(...)
go notifier.Run()
go ruleManager.Run()
go targetManager.Run()
go func() { errc <- webHandler.Run(ctx) }()
在此过程中,用到几个chan用于控制初始化的顺序:
dbOpen := make(chan struct{})
...
<-dbOpen
以上代码保证tsdb的正常启动
hup := make(chan os.Signal)
hupReady := make(chan bool)
signal.Notify(hup, syscall.SIGHUP)
...
close(hupReady)
以上代码启动配置重新加载的监听
启动过程用了大量的chan、go多线程,导致启动顺序和逻辑还比较复杂,经过这一天的仔细阅读后确实有种豁然开朗的感觉。