微服务之配置中心

「配置中心」的思路就是把项目中各种配置、各种参数、各种开关,全部都放到一个集中的地方进行统一管理,并提供一套标准的接口。 当各个服务需要获取配置的时候,就来「配置中心」的接口拉取。 当「配置中心」中的各种参数有更新的时候,也能通知到各个服务实时的过来同步最新的信息,使之动态更新。

除了管理配置的有点之外,引入配置中心的有点还有:

  • 当配置发生变化,需要重启配置,通过配置中心配合viper,配置中心可以实现配置动态修改。
  • 对于一些需要定时更新的配置,例如密钥,统一更新会非常方便
  • 避免多语言环境下导致的问题

技术选型

Golang技术栈的角度出发,推荐使用配置中心有两个选型,NacosApollo

img

作为学习目的,这里推荐使用Nacos,目前已经是官方支持。

Nacos

官方文档:

Nacos

Nacos Docker

通过docker安装

1
docker run --name nacos-quick -e MODE=standalone -p 8848:8848 -p 9848:9848 -d nacos/nacos-server:2.0.2

管理页面是 http://127.0.0.1:8848/nacos,用户名密码都是nacos

概念

  1. 命名空间

    隔离配置群,将某些配置集中放在某一个ns之下,例如数据库的配置,都可以放在一个db的ns中。

    命名空间一般用于区分微服务

  2. 组(GROUP)

    组用于区分环境组,例如开发环境、测试环境、生产环境

  3. 配置集(Data Id)

    一个配置集就是一个配置文件,可以很灵活

使用

Nacos-sdk-go

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

获取配置和监听配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package main

import (
"fmt"
"log"

"github.com/nacos-group/nacos-sdk-go/v2/clients"
"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
"github.com/nacos-group/nacos-sdk-go/v2/vo"
)

func main() {
// nacos服务端的配置
sc := []constant.ServerConfig{
{
IpAddr: "127.0.0.1",
Port: 8848,
},
}

// nacos获取配置的信息
cc := constant.ClientConfig{
NamespaceId: "b5688933-77cc-4079-8550-2e1a9c4b555b", // 如果需要支持多namespace,我们可以场景多个client,它们有不同的NamespaceId。当namespace是public时,此处填空字符串。
TimeoutMs: 5000,
NotLoadCacheAtStart: true,
LogDir: "./nacos/log",
CacheDir: "./nacos/cache", // 缓存,每次请求时,都会获取配置到本地缓存,如果配置中心无法访问,则使用本地缓存
LogLevel: "debug",
}

configClient, err := clients.NewConfigClient(
vo.NacosClientParam{
ClientConfig: &cc,
ServerConfigs: sc,
},
)
if err != nil {
log.Fatal(err)
}

config, err := configClient.GetConfig(vo.ConfigParam{
DataId: "db",
Group: "dev",
})
if err != nil {
log.Fatal(err)
}
fmt.Println(config)

err = configClient.ListenConfig(vo.ConfigParam{
DataId: "db",
Group: "dev",
OnChange: func(namespace, group, dataId, data string) {
fmt.Println("group:" + group + ", dataId:" + dataId + ", data:" + data)
},
})
if err != nil {
log.Fatal(err)
}
select {}
}

运行

1
2
3
4
5
6
7
2022/09/29 20:17:57 [INFO] logDir:<./nacos/log>   cacheDir:<./nacos/cache>
driver: postgres
source: host=base-stolon-proxy.base user=datatom dbname=processcenter sslmode=disable password=db_password port=5432 TimeZone=Asia/Shanghai

group:dev, dataId:db, data: driver: postgres
source: host=base-stolon-proxy.base user=datatom dbname=processcenter sslmode=disable password=db_password port=5432 TimeZone=Asia/Shanghai
abc: def

缓存配置

1
2
3
4
5
6
7
nacos
├── cache
│   └── config
│   └── db@@dev@@b5688933-77cc-4079-8550-2e1a9c4b555b
├── log
│   └── nacos-sdk.log
└── main.go

集成到服务中

go支持将json反序列化成struct

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

var Config Foo

type Foo struct {
DB `json:"db,omitempty"`
Bar `json:"bar,omitempty"`
}

type DB struct {
Driver string `json:"driver,omitempty"`
Source string `json:"source,omitempty"`
}

type Bar struct {
Num int `json:"num,omitempty"`
Switch bool `json:"switch,omitempty"`
}

通过反序列化成json即可

1
2
3
4
5
6
7
8
9
10
11
12
config, err := configClient.GetConfig(vo.ConfigParam{
DataId: "db",
Group: "dev",
})
if err != nil {
log.Fatal(err)
}

err = json.Unmarshal([]byte(config), &Config)
if err != nil {
log.Fatal(err)
}

推荐阅读:

微服务架构之「 配置中心 」

分布式配置中心(Nacos、Apollo)选型比较

Nacos、Apollo、Config 配置中心选型