14-分布式配置中心

一 分布式配置中心介绍

1.1 分布式配置中心作用

我们现在有一个项目, 使用Gin进行开发的, 配置文件是一个config.yaml的文件, 这个配置文件在项目启动时会被加载到内存中使用

考虑三种情况:

a . 添加配置项

1 . 你现在的用户服务有10个部署实例, 那么添加配置项需要去十个地方修改配置文件还得重新启动
2 . 即使Go的viper能完成修改配置文件自动生效, 那么其他语言是否能做到, 其他微服务是否一定会使用viper?

b . 修改配置项

大量的服务可能会使用同一个配置,比如要更新jwt的secret,这么多实例怎么办?

c . 开发,测试,生产环境如何隔离

前面虽然已经介绍了viper,但是依然一样的问题,那么多服务如何统一这种考虑因素;

所以

分布式配置中心可以实现不需要重启我们的服务器,动态的修改配置文件的内容

传统的配置文件读取方式

yaml格式

server:
	host: 127.0.0.1
  port: 8070
// 我们使用viper读取,并在项目中使用
虽然不重启项目,可以修改配置,项目也可以动态感知到
但是我们可以把常变动的配置信息存放在分布式配置中心上,
比如:请求的ip地址、系统的配置值、各种业务开关等等

1.2 常见的配置中心

	-携程的阿波罗(Apollo)
携程阿波罗(Apollo):构建环境非常复杂–底层架构的颗粒度拆分的非常细
文档:https://www.apolloconfig.com/#/zh/README
git地址:https://github.com/apolloconfig/apollo

​	-Spring Cloud Config
SpringCloud Config:属于spring体系,没有界面,配置文件内容存放在git上面

​	-Nacos(阿里)轻量级的配置中心
Nacos即可以作为注册中心,也可以作为分布式配置中心,轻量级的
git地址:https://github.com/alibaba/nacos/
文档地址:https://nacos.io/zh-cn/docs/what-is-nacos.html

a . apollo大而全, 功能完善, nacos小而全, 可以对比django和flask区别;
b . 部署nacos更加简单;
c . nacos不止支持配置中心还支持服务注册和发现;
d . 都支持各种语言, 不过apollo是第三方支持的,nacos是官方支持各种语言;


// nacos很活跃, 不过看的出来nacos想要构建的生态野心更大,我们使用Nacos分布式配置中心

img

二 Nacos分布式配置中心

2.1 Nacos安装

1.预备环境准备

Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:

  1. 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
  2. 64 bit JDK 1.8+;下载 & 配置
  3. Maven 3.2.x+;下载 & 配置

2.下载源码或者安装包

你可以通过源码和发行包两种方式来获取 Nacos。

从 Github 上下载源码方式
git clone https://github.com/alibaba/nacos.git
cd nacos/
mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U  
ls -al distribution/target/

// change the $version to your actual path
cd distribution/target/nacos-server-$version/nacos/bin
下载编译后压缩包方式

您可以从 最新稳定版本 下载 nacos-server-$version.zip 包。

unzip nacos-server-$version.zip 或者 tar -xvf nacos-server-$version.tar.gz
cd nacos/bin

3.启动服务器

  • 注:Nacos的运行需要以至少2C4g60g*3的机器配置下运行。
Linux/Unix/Mac

启动命令(standalone代表着单机模式运行,非集群模式):

sh startup.sh -m standalone

如果您使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

bash startup.sh -m standalone
Windows

启动命令(standalone代表着单机模式运行,非集群模式):

startup.cmd -m standalone

2.2 Docker安装

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

// 访问
http://10.0.0.102:8848/nacos/index.html#/login

//用户名密码:nacos/nacos
image-20220528185343677

三 Nacos基本使用

配置管理

默认带一个public命名空间,我们在该命名空间下可以建立一个配置

image-20220528203147721

image-20220528203554856

命名空间

可以隔离配置,用来区分微服务,一个服务一个命名空间,比如微服务中商品服务用一个命名空间,开发环境,测试环境,上线环境都放在这一个命名空间中

新建命名空间

image-20220528203704816

在新建的命名空间下新建配置-dev

image-20220528203816472

克隆配置成-pro

image-20220528203956879

一个微服务一个命名空间,一个配置项是一个Data ID,通过组可以区分一个微服务下不同的环境,如开发,测试,部署配置

group就是用来区分是开发,测试,线上配置的

例如:我们在一个商品微服务下,有web层配置rpc层配置文件,同时每一层又有开发,测试,线上配置,我们建立出来

//user-web.json----> dev
{
    "name":"user-web",
    "debug": true,
    "host":"127.0.0.1",
    "port":8080
}
//user-web.json----> pro
{
    "name":"user-web",
    "debug": false,
    "host":"0.0.0.0",
    "port":8080
}
//user-rpc.json----> dev
{
    "name":"user-rpc",
    "debug": true,
    "host":"127.0.0.1",
    "port":50051,
  	"mysql_host":"127.0.0.1",
    "mysql_prot":3306
}
//user-rpc.json----> pro
{
    "name":"user-web",
    "debug": false,
    "host":"0.0.0.0",
    "port":50051,
    "mysql_host":"10.0.0.102",
    "mysql_prot":3306
}

image-20220528205630357

四 go操作nacos

4.1 安装

// 参考地址:https://github.com/nacos-group/nacos-sdk-go/blob/master/README_CN.md
go get -u github.com/nacos-group/nacos-sdk-go

4.2 获取Nacos配置和监听配置

获取配置

会在项目路径下生成 /tmp/nacos/log,/tmp/nacos/cache,其实是下载到本地缓存了一份配置

package main

import (
	"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() {
	// 第一步:创建服务端配置
	// 至少一个ServerConfig
	serverConfigs := []constant.ServerConfig{
		{
			IpAddr: "10.0.0.102", // string Nacos的服务地址
			//ContextPath: "/nacos",
			Port:   8848, // uint64  Nacos的服务端口
			Scheme: "http",
		},
	}

	// 第二步:创建客户端配置clientConfig
	clientConfig := constant.ClientConfig{
		NamespaceId:         "0787cb8d-a743-4f8e-8955-624dd1a1ffca", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "/tmp/nacos/log",
		CacheDir:            "/tmp/nacos/cache",
		LogLevel:            "debug",
	}
	// 第三步:通过客户端配置和服务端配置 创建动态配置客户端
	client, err := clients.CreateConfigClient(map[string]interface{}{
		"serverConfigs": serverConfigs,
		"clientConfig":  clientConfig,
	})
	if err != nil {
		fmt.Println("创建动态客户端错误,", err)
		panic(err)
	}
	content, err := client.GetConfig(vo.ConfigParam{
		DataId: "user-web.json",
		Group:  "dev"})
	if err != nil {
		panic(err)
	}
	fmt.Println(content)
}

动态监听

package main

import (
	"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"
	"time"
)

func main() {
	// 第一步:创建服务端配置
	// 至少一个ServerConfig
	serverConfigs := []constant.ServerConfig{
		{
			IpAddr: "10.0.0.102", // string Nacos的服务地址
			//ContextPath: "/nacos",
			Port:   8848, // uint64  Nacos的服务端口
			Scheme: "http",
		},
	}

	// 第二步:创建客户端配置clientConfig
	clientConfig := constant.ClientConfig{
		NamespaceId:         "0787cb8d-a743-4f8e-8955-624dd1a1ffca", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "./tmp/nacos/log",
		CacheDir:            "./tmp/nacos/cache",
		LogLevel:            "debug",
	}
	// 第三步:通过客户端配置和服务端配置 创建动态配置客户端
	client, err := clients.CreateConfigClient(map[string]interface{}{
		"serverConfigs": serverConfigs,
		"clientConfig":  clientConfig,
	})
	if err != nil {
		fmt.Println("创建动态客户端错误,", err)
		panic(err)
	}
	// 第四步:获取配置文件内容
	content, err := client.GetConfig(vo.ConfigParam{
		DataId: "user-web.json",
		Group:  "dev"})
	if err != nil {
		panic(err)
	}
	fmt.Println(content)
	// 第五步:动态监听配置文件
	err = client.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)
		},
	})
	if err!=nil {
		panic(err)
	}
	time.Sleep(300*time.Second)
}

4.3 把配置文件信息转到结构体

package main

import (
	"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"
	"time"
)

type UserWebConfig struct {
	Name  string `json:"name"`
	Debug bool   `json:"debug"`
	Host  string `json:"host"`
	Port  int    `json:"port"`
}
func main() {
	var config UserWebConfig
	// 第一步:创建服务端配置
	// 至少一个ServerConfig
	serverConfigs := []constant.ServerConfig{
		{
			IpAddr: "10.0.0.102", // string Nacos的服务地址
			//ContextPath: "/nacos",
			Port:   8848, // uint64  Nacos的服务端口
			Scheme: "http",
		},
	}

	// 第二步:创建客户端配置clientConfig
	clientConfig := constant.ClientConfig{
		NamespaceId:         "0787cb8d-a743-4f8e-8955-624dd1a1ffca", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
		TimeoutMs:           5000,
		NotLoadCacheAtStart: true,
		LogDir:              "./tmp/nacos/log",
		CacheDir:            "./tmp/nacos/cache",
		LogLevel:            "debug",
	}
	// 第三步:通过客户端配置和服务端配置 创建动态配置客户端
	client, err := clients.CreateConfigClient(map[string]interface{}{
		"serverConfigs": serverConfigs,
		"clientConfig":  clientConfig,
	})
	if err != nil {
		fmt.Println("创建动态客户端错误,", err)
		panic(err)
	}
	// 第四步:获取配置文件内容
	content, err := client.GetConfig(vo.ConfigParam{
		DataId: "user-web.json",
		Group:  "dev"})
	if err != nil {
		panic(err)
	}
	fmt.Println(content)
	json.Unmarshal([]byte(content),&config)
	fmt.Println(config)
	// 第五步:动态监听配置文件
	err = client.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)
			json.Unmarshal([]byte(data),&config)
			fmt.Println(config)
		},
	})
	if err!=nil {
		panic(err)
	}
	time.Sleep(300*time.Second)
}

五 gin,rpc服务中集成

代码等同于上面
posted @ 2022-05-28 23:14  刘清政  阅读(518)  评论(0编辑  收藏  举报