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分布式配置中心
二 Nacos分布式配置中心
2.1 Nacos安装
1.预备环境准备
Nacos 依赖 Java 环境来运行。如果您是从代码开始构建并运行Nacos,还需要为此配置 Maven环境,请确保是在以下版本环境中安装使用:
- 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
- 64 bit JDK 1.8+;下载 & 配置。
- 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
三 Nacos基本使用
配置管理
默认带一个public命名空间,我们在该命名空间下可以建立一个配置
命名空间
可以隔离配置,用来区分微服务,一个服务一个命名空间,比如微服务中商品服务用一个命名空间,开发环境,测试环境,上线环境都放在这一个命名空间中
新建命名空间
在新建的命名空间下新建配置-dev
克隆配置成-pro
组
一个微服务一个命名空间,一个配置项是一个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
}
四 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服务中集成
代码等同于上面