Fork me on GitHub

分布式配置中心-nacos

一.为什么需要分布式配置中心

我们现在有一个项目,使用gin进行开发的,配置文件的话我们知道是一个叫做config.yaml的文件。我们也知道这个配置文件会在项目启动的时候被加载到内存中进行使用的。

考虑两种情况:

  • a.添加配置项
    i. 你现在的用户服务有10个部署实例,那么添加配置项你得去十个地方修改配置文件还得重新启动等。
    ii. 即使qo的viper能完成修改配置文件自动生效,那么你得考虑其他语言是否也能做到这点,其他的服务是否也一定会使用viper?
  • b.修改配置项大量的服务可能会使用同一个配置,比如我要更好wt的secrect,这么多实例怎么办? imooc
  • c.开发、测试、生产环境如何隔离:前面虽然已经介绍了viper,但是依然一样的问题,这么多服务如何统一这种考虑因素?

二.nacos的安装与配置

Nacos快速开始

1.安装nacos

1、下载

docker run --name nacos-standalone -e MODE=standalone -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m -p 8848:8848 -d nacos/nacos-server:latest

2、访问

http://ip:port/nacos/index.html
用户名密码:nacos/nacos

三.nacos的基础使用

1.命名空间

可以隔离配置集,将某些配置集放到某一个命名空间之下。
命名空间我们一般用来区分微服务

2.组

组可以用来区别开发、测试、生成环境

3.dataid-配置集

一个配置集就是一个配置文件,实际上可以更灵活

四.python集成nacos

nacos

pip install nacos-sdk-python

import nacos

SERVER_ADDERSSES = "server addresses split by comma"  # nacos "ip:port"
NAMESPACE = "***"  # namespace的id

# no auth mode
client = nacos.NacosClient(SERVER_ADDERSSES, namespace=NAMESPACE)
# auth mode
# client = nacos.NacosClient(SERVER_ADDRESSES, namespace=NAMESPACE, username="nacos", password="nacos")

# get config
data_id = "config.nacos"
group = "group"
print(client.get_config(data_id, group))

def test_cb(args)
    print("配置文件产生变化")
    print(args)

if __name__ == '__main__':
    # 监听,test_db 为函数名  
    client.add_config_watcher(data_id, group, test_cb)
    import time
    time.sleep(3000)

五.go操作nacos

nacos

go get -u github.com/nacos-group/nacos-sdk-go

package main

import (
	"OldPackageTest/nacos_test/config"
	"encoding/json"
	"fmt"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"
)

func main() {
	sc := []constant.ServerConfig{
		{
			IpAddr: "192.168.1.103",
			Port:   8848,
		},
	}

	cc := constant.ClientConfig{
		NamespaceId:         "c1872978-d51c-4188-a497-4e0cd20b97d5", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "tmp/nacos/log",
		CacheDir:            "tmp/nacos/cache",
		RotateTime:          "1h",
		MaxAge:              3,
		LogLevel:            "debug",
	}

	configClient, err := clients.CreateConfigClient(map[string]interface{}{
		"serverConfigs": sc,
		"clientConfig":  cc,
	})
	if err != nil {
		panic(err)
	}

	content, err := configClient.GetConfig(vo.ConfigParam{
		DataId: "user-web.json",
		Group:  "dev"})

	if err != nil {
		panic(err)
	}
	//fmt.Println(content) //字符串 - yaml
	serverConfig := config.ServerConfig{}
	//想要将一个json字符串转换成struct,需要去设置这个struct的tag
	json.Unmarshal([]byte(content), &serverConfig)
	fmt.Println(serverConfig)
	//err = configClient.ListenConfig(vo.ConfigParam{
	//	DataId: "user-web.json",
	//	Group:  "dev",
	//	OnChange: func(namespace, group, dataId, data string) {
	//		fmt.Println("配置文件变化")
	//		fmt.Println("group:" + group + ", dataId:" + dataId + ", data:" + data)
	//	},
	//})
	//time.Sleep(3000 * time.Second)
}

如何将nacos中的配置映射成go的struct

// go 语言本身支持将json的字符串反射成struct
json.Unmarshal([]byte(content), &global.ServerConfig)

initialize/config.go

package initialize

import (
	"encoding/json"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/nacos-group/nacos-sdk-go/clients"
	"github.com/nacos-group/nacos-sdk-go/common/constant"
	"github.com/nacos-group/nacos-sdk-go/vo"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"mxshop-api/user-web/global"
)

func GetEnvInfo(env string) bool {
	viper.AutomaticEnv()
	return viper.GetBool(env)
}

func InitConfig() {
	debug := GetEnvInfo("MXSHOP_DEBUG")
	configFilePrefix := "config"
	configFileName := fmt.Sprintf("user-web/%s-debug.yaml", configFilePrefix)
	if !debug {
		configFileName = fmt.Sprintf("user-web/%s-production.yaml", configFilePrefix)
	}

	v := viper.New()
	v.SetConfigFile(configFileName)
	if err := v.ReadInConfig(); err != nil {
		panic(err)
	}

	if err := v.Unmarshal(global.NacosConfig); err != nil {
		panic(err)
	}

	zap.S().Infof("配置信息: %v", global.NacosConfig)

	v.WatchConfig()
	v.OnConfigChange(func(e fsnotify.Event) {
		zap.S().Infof("config file changed: %v", e.Name)
		_ = v.ReadInConfig()
		_ = v.Unmarshal(global.NacosConfig)
		zap.S().Infof("配置信息: %v", global.NacosConfig)
	})

	sc := []constant.ServerConfig{
		{
			IpAddr: global.NacosConfig.Host,
			Port: uint64(global.NacosConfig.Port),
		},
	}

	cc := constant.ClientConfig{
		NamespaceId:         global.NacosConfig.NameSpace, // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "tmp/nacos/log",
		CacheDir:            "tmp/nacos/cache",
		RotateTime:          "1h",
		MaxAge:              3,
		LogLevel:            "debug",
	}

	configClient, err := clients.CreateConfigClient(map[string]interface{}{
		"serverConfigs": sc,
		"clientConfig":  cc,
	})
	if err != nil {
		panic(err)
	}

	content, err := configClient.GetConfig(vo.ConfigParam{
		DataId: global.NacosConfig.DataId,
		Group:  global.NacosConfig.Group})

	if err != nil {
		panic(err)
	}

	json.Unmarshal([]byte(content), &global.ServerConfig)

	err = configClient.ListenConfig(vo.ConfigParam{
		DataId: global.NacosConfig.DataId,
		Group:  global.NacosConfig.Group,
		OnChange: func(namespace, group, dataId, data string) {
			fmt.Println("配置文件变化")
			fmt.Println("group:" + group + ", dataId:" + dataId + ", data:" + data)
		},
	})
}
posted @ 2021-10-15 15:37  myboran  阅读(226)  评论(0)    收藏  举报