欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go kratos源碼及配置解析

 更新時間:2022年12月05日 11:57:55   作者:小宇渣渣渣  
這篇文章主要為大家介紹了go kratos源碼及配置解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

相關(guān)類圖

項目啟動時一般前置條件為解析配置文件, 我們看下這塊是怎么設(shè)計的.

流程解釋

  • config 實現(xiàn) config Interface 接口, 初始化reader對象
  • 調(diào)用Load方法, 通過入口注入的不同文件源, 調(diào)用實現(xiàn)了source interface 對應(yīng)的Load方法(以file舉例子)
  • file 通過 Load 入口, 判斷是目錄還是文件, 執(zhí)行對應(yīng)的方法, 拿到文件內(nèi)容返回
  • config 拿到file返回的內(nèi)容, 交給reader去合并
  • reader 根據(jù)文件格式(yml) 轉(zhuǎn)為 map[string]interface{} 結(jié)構(gòu), 并進行覆蓋合并, 將結(jié)果存到對象變量上
  • reader 處理完成后, config調(diào)用 file watcher 進行文件變更監(jiān)聽, 啟動協(xié)程監(jiān)聽

由此可見, config對象其實作為入口, 將數(shù)據(jù)生產(chǎn)交給file、env, 將數(shù)據(jù)加工解析交給 reader

代碼案例

init 接收外部參數(shù)定義解析配置文件地址

func init() {
	flag.StringVar(&commonconf, "common", "./configs/local", "common config path, eg: -conf config.yaml")
	flag.StringVar(&flagconf, "conf", "./configs/local/api", "config path, eg: -conf config.yaml")
    flag.Parse()
}

使用config.New初始化文件配置

//初始化配置
//新增兩個配置源, 文件格式 common and flagconf 路徑
c := config.New(
    config.WithSource(
        file.NewSource(commonconf),
        file.NewSource(flagconf),
    ),
)
// 關(guān)閉watch相關(guān)的監(jiān)聽器
defer c.Close()
// 加載配置文件
if err := c.Load(); err != nil {
	panic(err)
}
//解析配置到bc結(jié)構(gòu)上
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
    panic(err)
}

我們看下config.New的實現(xiàn)

// 初始化解析器, 關(guān)聯(lián)reader對象, 數(shù)據(jù)交給由reader加工和存儲
func New(opts ...Option) Config {
	o := options{
		decoder:  defaultDecoder,
		resolver: defaultResolver,
	}
	for _, opt := range opts {
		opt(&o)
	}
	return &config{
		opts:   o,
		reader: newReader(o),
	}
}

Options 有下面幾個屬性

type options struct {
	sources  []Source // 配置源, 由初始化負責(zé)傳入的source配置源
	decoder  Decoder //  解析器
	resolver Resolver // 變量解析替換
}

執(zhí)行 Load 配置加載

func (c *config) Load() error {
    // 因為我們在入口傳入的是file對象, 所以執(zhí)行src load的時候也是file對象的 load 方法
	for _, src := range c.opts.sources {
        // 獲取文件內(nèi)容(可能是一個目錄, 會存在多個文件)
		kvs, err := src.Load()
		if err != nil {
			return err
		}
		for _, v := range kvs {
			log.Debugf("config loaded: %s format: %s", v.Key, v.Format)
		}
        // 合并配置key
		if err = c.reader.Merge(kvs...); err != nil {
			log.Errorf("failed to merge config source: %v", err)
			return err
		}
        // 調(diào)用file watch, 監(jiān)聽文件變化
		w, err := src.Watch()
		if err != nil {
			log.Errorf("failed to watch config source: %v", err)
			return err
		}
		c.watchers = append(c.watchers, w)
        // 異步監(jiān)聽文件變化(調(diào)用對應(yīng)的watch對象)
		go c.watch(w)
	}
    // 解析內(nèi)容中是否包含 ${APPID:default} 變量
    // 如果在配置文件中存在 APPID: xx 配置, 則進行替換
    // 否則使用default默認值
	if err := c.reader.Resolve(); err != nil {
		log.Errorf("failed to resolve config source: %v", err)
		return err
	}
	return nil
}

異步watch

func (c *config) watch(w Watcher) {
	for {
		kvs, err := w.Next()
		if err != nil {
			if errors.Is(err, context.Canceled) {
				log.Infof("watcher's ctx cancel : %v", err)
				return
			}
			time.Sleep(time.Second)
			log.Errorf("failed to watch 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.TypeOf(n.Load()) == reflect.TypeOf(v.Load()) && !reflect.DeepEqual(n.Load(), v.Load()) {
				v.Store(n.Load())
				if o, ok := c.observers.Load(k); ok {
					o.(Observer)(k, v)
				}
			}
			return true
		})
	}
}

Scan 將配置轉(zhuǎn)換成結(jié)構(gòu)體

var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
    panic(err)
}

以上就是go kratos源碼及配置解析的詳細內(nèi)容,更多關(guān)于kratos源碼配置的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論