client 接入指南
On this page
配置被 Sail 管理起来后,如何获取这些配置呢?目前市面的配置中心无非两种流派:
- SDK 集成
类似 Nacos、Apollo 都是这种方式,提供一个语言特定的 sdk,集成 sdk 即可。
- sidecar 外挂
类似 confd 是这种方式,外挂一个进程,专门负责输出和更新配置文件,程序还是读取配置,侵入性小。
这两种方式,sail 的 client 都是支持的,请看下图:

由于 sail-client 会把从 etcd 中读取的配置备份到文件,并保持文件内容的更新,所以,从使用者的角度来说, 既可以把 sail-client 集成到代码中,也可以单独运行 sail-client,然后去读取备份的配置文件。
安装
代码接入:
go get github.com/HYY-yu/sail-client
单独运行:
git clone https://github.com/HYY-yu/sail-client.git
# 修改 cfg.toml 为你的配置
vim cfg.toml
go build -o service ./cmd/main.go
./service
# 打包成 docker 镜像
CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -o service ./cmd/main.go
docker build --build-arg=serviceName=sail-client -f ./deploy/Dockerfile .
代码接入使用方式
1. New 一个 sail 实例
前面我们说了,sail-client 运行需要元配置,而元配置信息可以从 Sail 中获取。
获取后,可以通过 toml 、 环境变量 、 启动 flag 注入:
// 通过读取 toml 文件
s := sail.NewWithToml("your_config.toml")
if s.Err() != nil{
panic(s.Err())
}
// 通过读取环境变量
s := sail.NewWithEnv()
if s.Err() != nil{
panic(s.Err())
}
// 通过读取启动 flag
s := sail.NewWithFlag()
if s.Err() != nil{
panic(s.Err())
}
2. 运行 Pull() 获取配置
err := s.Pull()
if err != nil{
panic(err)
}
第二步就要去 ETCD 拉配置了,也很容易理解。
这里如果访问不到 ETCD,会尝试去读取备份配置文件,并持续重连 etcd,不会报错,只会打印警告日志,需要注意。
3. 从代码中获取配置
本质上,sail-client 内部就是把配置信息存到了 viper 实例,所以你如果用的是 viper,那获取方式跟 viper 是一模一样的。
如果你没用过 viper,那可以看看以下简单的介绍:
# 假设有如下两个配置文件:
# mysql.toml
[mysql]
addr="127.0.0.1:3306"
database="sail"
# redis.yaml
redis:
host: 127.0.0.1
port: 6789
db: 1
通过 Key 就可以获取到配置信息,嵌套的 key 可以用.分隔。
// GetXXX ,MustGetXXX 获取配置
redisHost := s.MustGetString("redis.host")
redisDB := s.MustGetInt("redis.db")
mysqlDb := s.MustGetString("mysql.database")
...
如果你的代码是使用了一个结构体,比如:
type Config struct{
Mysql struct{
Addr string
Database string
}
Redis struct{
Host string
Port int
Db int
}
}
可以通过 viper 的 Unmarshal 填充,注意结构体不会被自动更新:
cfg := &Config{}
// 直接获取一个 viper 实例,包含了所有的配置
newViper,err:= s.MergeVipers()
if err != nil{
panic(err)
}
newViper.Unmarshal(&cfg)
在配置更新时,收到回调,比如,在收到配置更新时,更新上面的结构体Config:
// 需要在初始化时,传回调函数
sail := sailclient.NewWithToml("./cfg.toml",
sailclient.WithOnConfigChange(func(configFileKey string, s *sailclient.Sail) {
log.Println("find key change - ",configFileKey)
log.Println("new value: ",s.MustGetString("test.log"))
// 更新结构体
newViper,err:= s.MergeVipers()
if err != nil{
panic(err)
}
newViper.Unmarshal(&cfg)
})
)
if sail.Err() != nil {
log.Fatalln(sail.Err())
}
你也可以在回调函数中做更多的操作。
4. 更多使用技巧,请阅读 sail-client 源码
阅读源码并不难,sail-client 实现是很简单的,效率会比看文档高多了。
关于配置文件中重复 key 的提示
重复 key 的支持,这里需要着重提下,如果你能保证你的配置文件内不会有重复的 key,那可以不看下面的内容。
注意,这不是重复 key:
# 假设有如下两个配置文件:
# mysql.toml
[mysql]
addr="127.0.0.1:3306"
database="sail"
# redis.yaml
redis:
addr: 127.0.0.1
port: 6789
db: 1
# 虽然两个配置文件中都有 addr,但它们属于不同的父 key。
这是重复 key:
# 假设有如下两个配置文件:
# mysql.toml
addr="127.0.0.1:3306"
database="sail"
# redis.yaml
addr: 127.0.0.1
port: 6789
碰到重复key,需要用 GetXXWithName 限定:
mysqlAddr := s.GetStringWithName("addr","mysql.toml")
redisAddr := s.GetStringWithName("addr","redis.yaml")
重复 key 要 merge 成一个 viper 实例,需要用下面的方法:
newViper,err := s.MergeVipersWithName()
if err != nil{
panic(err)
}
// 获取时,带上文件名
newViper.Get("mysql.toml.addr")