nacos viper remote provider
This commit is contained in:
		
							
								
								
									
										74
									
								
								example/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								example/main.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
 | 
						remote "github.com/yoyofxteam/nacos-viper-remote"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"os/signal"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						config_viper := viper.New()
 | 
				
			||||||
 | 
						runtime_viper := config_viper
 | 
				
			||||||
 | 
						runtime_viper.SetConfigFile("./example_config.yaml")
 | 
				
			||||||
 | 
						_ = runtime_viper.ReadInConfig()
 | 
				
			||||||
 | 
						var option *remote.Option
 | 
				
			||||||
 | 
						_ = runtime_viper.Sub("yoyogo.cloud.discovery.metadata").Unmarshal(&option)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						remote.SetOptions(option)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//remote.SetOptions(&remote.Option{
 | 
				
			||||||
 | 
						//	Url:         "localhost",
 | 
				
			||||||
 | 
						//	Port:        80,
 | 
				
			||||||
 | 
						//	NamespaceId: "public",
 | 
				
			||||||
 | 
						//	GroupName:   "DEFAULT_GROUP",
 | 
				
			||||||
 | 
						//	Config: 	 remote.Config{ DataId: "config_dev" },
 | 
				
			||||||
 | 
						//	Auth:        nil,
 | 
				
			||||||
 | 
						//})
 | 
				
			||||||
 | 
						//localSetting := runtime_viper.AllSettings()
 | 
				
			||||||
 | 
						remote_viper := viper.New()
 | 
				
			||||||
 | 
						err := remote_viper.AddRemoteProvider("nacos", "localhost", "")
 | 
				
			||||||
 | 
						remote_viper.SetConfigType("yaml")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = remote_viper.ReadRemoteConfig()
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							err = remote_viper.WatchRemoteConfigOnChannel()
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								config_viper = remote_viper
 | 
				
			||||||
 | 
								fmt.Println("used remote viper")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						appName := config_viper.GetString("yoyogo.application.name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println(appName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								time.Sleep(time.Second * 30) // delay after each request
 | 
				
			||||||
 | 
								appName = config_viper.GetString("yoyogo.application.name")
 | 
				
			||||||
 | 
								fmt.Println(appName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						onExit()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func onExit() {
 | 
				
			||||||
 | 
						c := make(chan os.Signal)
 | 
				
			||||||
 | 
						signal.Notify(c, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM,
 | 
				
			||||||
 | 
							syscall.SIGQUIT, syscall.SIGUSR1, syscall.SIGUSR2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for s := range c {
 | 
				
			||||||
 | 
							switch s {
 | 
				
			||||||
 | 
							case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
 | 
				
			||||||
 | 
								fmt.Println("Program Exit...", s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								fmt.Println("other signal", s)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								example_config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								example_config.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					yoyogo:
 | 
				
			||||||
 | 
					  application:
 | 
				
			||||||
 | 
					    name: yoyogo_demo_dev
 | 
				
			||||||
 | 
					  cloud:
 | 
				
			||||||
 | 
					    discovery:
 | 
				
			||||||
 | 
					      cache:
 | 
				
			||||||
 | 
					        ttl: 30     # seconds
 | 
				
			||||||
 | 
					      strategy: "round-robin"    # round-robin  , weight-time ,  random
 | 
				
			||||||
 | 
					      type: "nacos"
 | 
				
			||||||
 | 
					      metadata:
 | 
				
			||||||
 | 
					        url: "120.53.133.30"
 | 
				
			||||||
 | 
					        port: 80
 | 
				
			||||||
 | 
					        namespace: "public"
 | 
				
			||||||
 | 
					        group: "DEFAULT_GROUP"
 | 
				
			||||||
 | 
					        configserver:
 | 
				
			||||||
 | 
					          dataId: "config_dev"
 | 
				
			||||||
 | 
					        auth:
 | 
				
			||||||
 | 
					          enable: true
 | 
				
			||||||
 | 
					          username: "root"
 | 
				
			||||||
 | 
					          password: "1234"
 | 
				
			||||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					module github.com/yoyofxteam/nacos-viper-remote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					go 1.14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require (
 | 
				
			||||||
 | 
						github.com/spf13/viper v1.7.1
 | 
				
			||||||
 | 
						github.com/nacos-group/nacos-sdk-go v1.0.7
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
							
								
								
									
										94
									
								
								nacos_manager.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								nacos_manager.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					package nacos_viper_remote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/nacos-group/nacos-sdk-go/clients"
 | 
				
			||||||
 | 
						"github.com/nacos-group/nacos-sdk-go/clients/config_client"
 | 
				
			||||||
 | 
						"github.com/nacos-group/nacos-sdk-go/common/constant"
 | 
				
			||||||
 | 
						"github.com/nacos-group/nacos-sdk-go/common/logger"
 | 
				
			||||||
 | 
						"github.com/nacos-group/nacos-sdk-go/vo"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type nacosConfigManager struct {
 | 
				
			||||||
 | 
						client config_client.IConfigClient
 | 
				
			||||||
 | 
						option *Option
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewNacosConfigManager(option *Option) (*nacosConfigManager, error) {
 | 
				
			||||||
 | 
						var serverConfigs []constant.ServerConfig
 | 
				
			||||||
 | 
						urls := strings.Split(option.Url, ";")
 | 
				
			||||||
 | 
						for _, url := range urls {
 | 
				
			||||||
 | 
							serverConfigs = append(serverConfigs, constant.ServerConfig{
 | 
				
			||||||
 | 
								ContextPath: "/nacos",
 | 
				
			||||||
 | 
								IpAddr:      url,
 | 
				
			||||||
 | 
								Port:        option.Port,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						clientConfig := constant.ClientConfig{
 | 
				
			||||||
 | 
							NamespaceId:         option.NamespaceId,
 | 
				
			||||||
 | 
							TimeoutMs:           5000,
 | 
				
			||||||
 | 
							NotLoadCacheAtStart: true,
 | 
				
			||||||
 | 
							RotateTime:          "1h",
 | 
				
			||||||
 | 
							MaxAge:              3,
 | 
				
			||||||
 | 
							LogLevel:            "info",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if option.Auth != nil && option.Auth.Enable {
 | 
				
			||||||
 | 
							clientConfig.Username = option.Auth.User
 | 
				
			||||||
 | 
							clientConfig.Password = option.Auth.Password
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						client, err := clients.CreateConfigClient(map[string]interface{}{
 | 
				
			||||||
 | 
							"serverConfigs": serverConfigs,
 | 
				
			||||||
 | 
							"clientConfig":  clientConfig,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							logger.Error(err.Error())
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager := &nacosConfigManager{client: client, option: option}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return manager, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cm *nacosConfigManager) Get(dataId string) ([]byte, error) {
 | 
				
			||||||
 | 
						//get config
 | 
				
			||||||
 | 
						content, err := cm.client.GetConfig(vo.ConfigParam{
 | 
				
			||||||
 | 
							DataId: cm.option.Config.DataId,
 | 
				
			||||||
 | 
							Group:  cm.option.GroupName,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return []byte(content), err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cm *nacosConfigManager) Watch(dataId string, stop chan bool) <-chan *viper.RemoteResponse {
 | 
				
			||||||
 | 
						resp := make(chan *viper.RemoteResponse)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						configParams := vo.ConfigParam{
 | 
				
			||||||
 | 
							DataId: cm.option.Config.DataId,
 | 
				
			||||||
 | 
							Group:  cm.option.GroupName,
 | 
				
			||||||
 | 
							OnChange: func(namespace, group, dataId, data string) {
 | 
				
			||||||
 | 
								fmt.Println("config changed group:" + group + ", dataId:" + dataId)
 | 
				
			||||||
 | 
								resp <- &viper.RemoteResponse{
 | 
				
			||||||
 | 
									Value: []byte(data),
 | 
				
			||||||
 | 
									Error: nil,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err := cm.client.ListenConfig(configParams)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								select {
 | 
				
			||||||
 | 
								case <-stop:
 | 
				
			||||||
 | 
									_ = cm.client.CancelListenConfig(configParams)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return resp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								nacos_options.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								nacos_options.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					package nacos_viper_remote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Option struct {
 | 
				
			||||||
 | 
						Url         string `mapstructure:"url"`
 | 
				
			||||||
 | 
						Port        uint64 `mapstructure:"port"`
 | 
				
			||||||
 | 
						NamespaceId string `mapstructure:"namespace"`
 | 
				
			||||||
 | 
						GroupName   string `mapstructure:"group"`
 | 
				
			||||||
 | 
						Config      Config `mapstructure:"configserver"`
 | 
				
			||||||
 | 
						Auth        *Auth  `mapstructure:"auth"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Config struct {
 | 
				
			||||||
 | 
						DataId string `mapstructure:"dataId"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Auth struct {
 | 
				
			||||||
 | 
						Enable   bool   `mapstructure:"enable"`
 | 
				
			||||||
 | 
						User     string `mapstructure:"username"`
 | 
				
			||||||
 | 
						Password string `mapstructure:"password"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										8
									
								
								viper_manager.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								viper_manager.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					package nacos_viper_remote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "github.com/spf13/viper"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type viperConfigManager interface {
 | 
				
			||||||
 | 
						Get(key string) ([]byte, error)
 | 
				
			||||||
 | 
						Watch(key string, stop chan bool) <-chan *viper.RemoteResponse
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										66
									
								
								viper_remote.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								viper_remote.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					package nacos_viper_remote
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var nacosOptions = &Option{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetOptions(option *Option) {
 | 
				
			||||||
 | 
						nacosOptions = option
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type remoteConfigProvider struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (rc *remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
 | 
				
			||||||
 | 
						cmt, err := getConfigManager(rp)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var b []byte
 | 
				
			||||||
 | 
						switch cm := cmt.(type) {
 | 
				
			||||||
 | 
						case viperConfigManager:
 | 
				
			||||||
 | 
							b, err = cm.Get(rp.Path())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return bytes.NewReader(b), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (rc *remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
 | 
				
			||||||
 | 
						return rc.Get(rp)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (rc *remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
 | 
				
			||||||
 | 
						cmt, err := getConfigManager(rp)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch cm := cmt.(type) {
 | 
				
			||||||
 | 
						case viperConfigManager:
 | 
				
			||||||
 | 
							quit := make(chan bool)
 | 
				
			||||||
 | 
							viperResponseCh := cm.Watch("dataId", quit)
 | 
				
			||||||
 | 
							return viperResponseCh, quit
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getConfigManager(rp viper.RemoteProvider) (interface{}, error) {
 | 
				
			||||||
 | 
						if rp.Provider() == "nacos" {
 | 
				
			||||||
 | 
							return NewNacosConfigManager(nacosOptions)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							return nil, errors.New("The Nacos configuration manager is not supported!")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						viper.SupportedRemoteProviders = []string{"nacos"}
 | 
				
			||||||
 | 
						viper.RemoteConfig = &remoteConfigProvider{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user