nacos viper remote provider
This commit is contained in:
parent
20220cb36f
commit
bcd01f97cc
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{}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user