实现viper.remoteConfigFactory接口#
type remoteConfigProvider struct{}
//这个接口是在第一次读取远程配置时调用,viper.ReadRemoteConfig()
func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
log.Println("Getting config from remote", rp)
r := bytes.NewReader([]byte("{\"a\":1}"))
time.Sleep(time.Second)
return r, nil
}
//这个接口是在客户端调用viper.WatchRemoteConfig(), 只监听一次变化
func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
//这里写你获取配置的方法
log.Println("Watching config from remote", rp)
s := fmt.Sprintf(`{"app":{"name":"test","version":%d}}`, time.Now().Unix())
r := bytes.NewReader([]byte(s))
time.Sleep(time.Second)
return r, nil
}
//这个接口是在客户端调用viper.GetViper().WatchRemoteConfigOnChannel()时,监听多次变化
func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
log.Println("Watching Channel config from remote", rp)
ch := make(chan *viper.RemoteResponse)
go func() {
//defer close(ch) viper里面使用死循环来处理,如果关闭管道会返回nil, 而viper没有处理,会报painc,所以不用关闭,viper是想让你在整个生命周期都监听
//这里写你获取配置的方法
for i := 0; ; i++ {
ch <- &viper.RemoteResponse{
Value: []byte(fmt.Sprintf(`{"app":{"name":"test","version":%d}}`, time.Now().Unix())),
}
time.Sleep(time.Second)
}
}()
return ch, nil
}
设置viper必要参数#
func init() {
viper.RemoteConfig = remoteConfigProvider{} //把我们写的provider设置好,否则监听不会生效
viper.SupportedRemoteProviders = []string{"app"} //这里名称需要设置好,和下面添加的名称需要一致
}
使用viper#
viper.SetConfigType("json") //需要和返回的数据格式一致,不然无法解析
viper.AddRemoteProvider("app", ":8080", "/aabb/cc") //app就是上面的SupportedRemoteProviders,viper内部会校验是否包含,后面两个参数根据自己的需求来填写
viper.ReadRemoteConfig() //加载远程配置
// viper.WatchRemoteConfig() //一次性监听配置,阻塞
viper.GetViper().WatchRemoteConfigOnChannel() //一直监听,非阻塞