导包时也只保留了核心包。

package main

import (
    clientv3 "go.etcd.io/etcd/client/v3"
)

type Config struct {
    Addr           string `json:"addr"`
    AesKey         string `json:"aes_key"`
    HTTPS          bool   `json:"https"`
    Secret         string `json:"secret"`
    PrivateKeyPath string `json:"private_key_path"`
    CertFilePath   string `json:"cert_file_path"`
}

var (
    appConfig  Config
    configPath = `/configs/remote_config.json`
    client     *clientv3.Client
    err        error
)

func init() {
    client, err = clientv3.New(clientv3.Config{
        Endpoints:   []string{"http://127.0.0.1:2379"},
        DialTimeout: 5 * time.Second,
    })
    if err != nil {
        panic(err)
    }

    initConfig()
}

func watchAndUpdate() {
    watch := client.Watch(context.Background(), configPath)

    for wresp := range watch {
        for _, ev := range wresp.Events {
            log.Println("new values is ", string(ev.Kv.Value))
            err = json.Unmarshal(ev.Kv.Value, &appConfig)
            if err != nil {
                log.Fatalln(err)
            }
        }
    }

}

func initConfig() {
    var resp *clientv3.GetResponse
    resp, err = client.Get(context.Background(), configPath)
    if err != nil {
        panic(err)
    }
    json.Unmarshal(resp.Kvs[0].Value, &appConfig)
}

func getConfig() Config {
    return appConfig
}

func main() {
    defer client.Close()
    watchAndUpdate()
}

上述代码在更新配置时进行了一系列操作:watch 响应、json 解析,这些操作都不具备原子性。当单个业务请求流程中多次获取 config 时,有可能因为中途 config 发生变化而导致单个请求前后逻辑不一致。因此,在使用类似方法进行更新配置时,需要在单个请求的生命周期内使用相同的配置。具体实现方式可以是只在请求开始时获取一次配置,然后依次向下透传。当然具体情况需要具体分析。

最后编辑: kuteng  文档更新时间: 2022-03-22 19:29   作者:kuteng