在上文我們的 go學習筆記:使用 consul 做服務發現和配置共享 這里我們單獨來用viper實現讀取consul的配置, 我習慣與用yaml格式, 所以 首先 新建yaml文件
store: book: - author: john price: 10 - author: ken price: 12 bicycle: color: red price: 19.95
可以直接調用viper.AddRemoteProvider讀取遠程配置, 也可以用github.com/hashicorp/consul/api 來讀取consul的內容, 然后在用viper讀取,整改代碼如下:
package main
import (
"bytes"
"fmt"
"log"
"time"
consulapi "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/api/watch"
"github.com/spf13/viper"
_ "github.com/spf13/viper/remote"
)
var (
defaultConfig *viper.Viper
consulAddress string
consulPath string
)
func initConfig() *viper.Viper {
consulAddress = "http://192.168.100.19:8500"
consulPath = "config/v1/local"
defaultConfig = viper.New()
defaultConfig.SetConfigType("yaml")
consulClient, err := consulapi.NewClient(&consulapi.Config{Address: consulAddress})
if err != nil {
log.Fatalln("consul連接失敗:", err)
}
kv, _, err := consulClient.KV().Get(consulPath, nil)
if err != nil {
log.Fatalln("consul獲取配置失敗:", err)
}
err = defaultConfig.ReadConfig(bytes.NewBuffer(kv.Value))
if err != nil {
log.Fatalln("Viper解析配置失敗:", err)
}
go watchConfig()
return defaultConfig
}
func watchConfig() {
time.Sleep(time.Second * 10)
params := make(map[string]interface{})
params["type"] = "key"
params["key"] = consulPath
w, err := watch.Parse(params)
if err != nil {
log.Fatalln(err)
}
w.Handler = func(u uint64, i interface{}) {
kv := i.(*consulapi.KVPair)
hotconfig := viper.New()
hotconfig.SetConfigType("yaml")
err = hotconfig.ReadConfig(bytes.NewBuffer(kv.Value))
if err != nil {
log.Fatalln("Viper解析配置失敗:", err)
}
defaultConfig = hotconfig
}
err = w.Run(consulAddress)
if err != nil {
log.Fatalln("監聽consul錯誤:", err)
}
}
func GetConfig() *viper.Viper {
if defaultConfig == nil {
defaultConfig = initConfig()
}
return defaultConfig
}
func main() {
ReadOne()
go func() {
for {
host := GetConfig().GetString("store.bicycle.color")
fmt.Println("consul===", host)
time.Sleep(time.Second * 10)
}
}()
select {}
}
func ReadOne() {
runtimeConfig := viper.New()
runtimeConfig.AddRemoteProvider("consul", "http://192.168.100.19:8500", "config/v1/local")
runtimeConfig.SetConfigType("yaml")
err := runtimeConfig.ReadRemoteConfig()
if err != nil {
log.Fatalln("viper read:", err)
}
err = runtimeConfig.WatchRemoteConfigOnChannel()
if err != nil {
log.Fatalln("viper watch err:", err)
}
go func() {
for {
host := runtimeConfig.GetString("store.bicycle.color")
fmt.Println("viper=====", host)
time.Sleep(time.Second * 10)
}
}()
}
如果遇到 google.golang.org/grpc/naming: module google.golang.org/grpc@latest found (v1.31.0), but does not contain package google.golang.org/grpc/naming 這樣的錯誤,可以在go.mod文件增加:
replace google.golang.org/grpc => google.golang.org/grpc v1.21.1