micro.newService()中 newOptions
func newOptions(opts ...Option) Options {
opt := Options{
Auth: auth.DefaultAuth,
Broker: broker.DefaultBroker,
Cmd: cmd.DefaultCmd,
Config: config.DefaultConfig,
Client: client.DefaultClient,
Server: server.DefaultServer,
Store: store.DefaultStore,
Registry: registry.DefaultRegistry,
Router: router.DefaultRouter,
Runtime: runtime.DefaultRuntime,
Transport: transport.DefaultTransport,
Context: context.Background(),
Signal: true,
}
for _, o := range opts {o(&opt)
}
return opt
}
初始化了一堆根底设置,来看看 configconfig.DefaultConfig,
在 config/config.go 中
var (
// Default Config Manager
DefaultConfig, _ = NewConfig())
// NewConfig returns new config
func NewConfig(opts ...Option) (Config, error) {return newConfig(opts...)
}
func newConfig(opts ...Option) (Config, error) {
var c config
c.Init(opts...)
go c.run()
return &c, nil
}
func (c *config) Init(opts ...Option) error {
c.opts = Options{Reader: json.NewReader(),
}
c.exit = make(chan bool)
for _, o := range opts {o(&c.opts)
}
// default loader uses the configured reader
if c.opts.Loader == nil {c.opts.Loader = memory.NewLoader(memory.WithReader(c.opts.Reader))
}
err := c.opts.Loader.Load(c.opts.Source...)
if err != nil {return err}
c.snap, err = c.opts.Loader.Snapshot()
if err != nil {return err}
c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet)
if err != nil {return err}
return nil
}
func (c *config) run() {watch := func(w loader.Watcher) error {
for {
// get changeset
snap, err := w.Next()
if err != nil {return err}
c.Lock()
if c.snap.Version >= snap.Version {c.Unlock()
continue
}
// save
c.snap = snap
// set values
c.vals, _ = c.opts.Reader.Values(snap.ChangeSet)
c.Unlock()}
}
for {w, err := c.opts.Loader.Watch()
if err != nil {time.Sleep(time.Second)
continue
}
done := make(chan bool)
// the stop watch func
go func() {
select {
case <-done:
case <-c.exit:
}
w.Stop()}()
// block watch
if err := watch(w); err != nil {
// do something better
time.Sleep(time.Second)
}
// close done chan
close(done)
// if the config is closed exit
select {
case <-c.exit:
return
default:
}
}
}
看看 Init()
左做了什么
- 初始化并设置 opts,创立 exit 用于监听退出信号,设置 opts
-
设置默认 loader,c.opts.Loader 默认是 memory
memory.NewLoader()
[config/loader/memory/memory.go]- 初始化并设置 opts,蕴含 Reader[默认 json]
- 初始化 memory{}
-
设置 m.sets, 并
watch()
每个 options.Source,看看watch()
做了什么-
定义 watch()函数
-
调用 watcher.Next(), 上面看看 next()做了什么
- 定义 update()函数,返回 loader.Snapshot{}
- 监听 watcher.exit,watcher.updates 信号,有更新时且版本更新时,调用下面的 update()函数,更新 watcher.value 并返回 loader.Snapshot{}
- 保留 m.sets[idx],值为 loader.Snapshot{}
- 合并所有 m.sets
- 读取所有值到 m.vals, 保留快照到 m.snap
-
调用 update()
- 获取所有 watcher,如果版本有更新,则发送 watcher.updates 信号
-
-
调用 Watch()函数返回 watcher,留神 W 是大写, 调用的是 memory.Watch()
- 调用 Get(),返回 m.vals.Get(path…)
- 初始化 watcher,并增加到 m.watchers【双向链表】
- 开协程,监听 watcher.exit 信号, 收到信号从 watchers 中移除以后 watcher
- 开协程,监听实现信号 done 和 exit 信号,收到信号后执行 Stop(), 敞开 exit,updates 这 2 个 channel
- 调用下面定义的 watch()
- 敞开 done channel,监听 m.exit 信号
-
-
调用 c.opts.Loader.Load()
- 循环所有 source,更新 m.sources,m.sets, 并 watch()所有 source
-
调用
reload()
- 合并所有 sets
- 设置 m.vals,m.snap
- 调用 m.update()
-
调用
c.opts.Loader.Snapshot()
- 如曾经 load,间接复制一份并返回 m.snap
- 没载入就调用
Sync()
同步配置 - 复制一份 m.snap 返回
- 调用
c.opts.Reader.Values()
,赋值 config.vals【reader.Values
类型】
绕来绕去,终于完了。
主流程其实并不简单,次要是波及到 watch 更新,所以比拟绕。
config 这块其实是比拟独立的包,能够在其余我的项目中援用。