源码 kratos 配置热加载分析
源码 kratos 配置热加载分析
github.com\go-kratos\kratos\v2@v2.1.2\config\value.go
github.com/go-kratos/kratos/v2@v2.1.2/config/config.go:40
通过go程开启监听文件变动的功能
package main
import (
"fmt"
"time"
)
func forever() {
for {
fmt.Println("forever", time.Now())
time.Sleep(8 * time.Second)
}
}
func main() {
go forever()
for {
fmt.Println("main", time.Now())
time.Sleep(4 * time.Second)
}
}
c := config.New(
config.WithSource(
file.NewSource(flagconf),
),
)
defer c.Close()
if err := c.Load(); err != nil {
panic(err)
}
func (c *config) Load() error {
for _, src := range c.opts.sources {
kvs, err := src.Load()
if err != nil {
return err
}
for _, v := range kvs {
c.log.Infof("config loaded: %s format: %s", v.Key, v.Format)
}
if err = c.reader.Merge(kvs...); err != nil {
c.log.Errorf("failed to merge config source: %v", err)
return err
}
w, err := src.Watch()
if err != nil {
c.log.Errorf("failed to watch config source: %v", err)
return err
}
c.watchers = append(c.watchers, w)
go c.watch(w)
}
if err := c.reader.Resolve(); err != nil {
c.log.Errorf("failed to resolve config source: %v", err)
return err
}
return nil
}
func (c *config) watch(w Watcher) {
for {
kvs, err := w.Next()
if errors.Is(err, context.Canceled) {
c.log.Infof("watcher's ctx cancel : %v", err)
return
}
if err != nil {
time.Sleep(time.Second)
c.log.Errorf("failed to watch next config: %v", err)
continue
}
if err := c.reader.Merge(kvs...); err != nil {
c.log.Errorf("failed to merge next config: %v", err)
continue
}
if err := c.reader.Resolve(); err != nil {
c.log.Errorf("failed to resolve next config: %v", err)
continue
}
c.cached.Range(func(key, value interface{}) bool {
k := key.(string)
v := value.(Value)
if n, ok := c.reader.Value(k); ok && !reflect.DeepEqual(n.Load(), v.Load()) {
v.Store(n.Load())
if o, ok := c.observers.Load(k); ok {
o.(Observer)(k, v)
}
}
return true
})
}
}