在 [微服务二] 这篇文章中,简单谈了从 nacos 读取服务配置文件。在 [微服务七] 这篇文章中,谈了制作 Dockerfile,通过 docker 将 Go 项目部署并运行在服务器上。在 [微服务八] 谈了使用 shell 脚本一键重新构建基于 Docker 的 Go 项目。
这篇文章中,实现动态获取 nacos 对应的配置文件。在 [微服务二] 这篇文章中,获取 nacos 配置文件,是在代码里面写的 nacos 的 ip、端口、组、DataID。这样写,如果要读取其他配置文件就要改动代码,及其的不方便。如果在项目目录写成配置文件,也行。但是每次打包项目上传服务器,配置文件也要上传。不太方便。>[微服务二]这篇文章中,获取 nacos 配置文件,是在代码里面写的 nacos 的 ip、端口、组、DataID。这样写,如果要读取其他配置文件就要改动代码,及其的不方便。如果在项目目录写成配置文件,也行。但是每次打包项目上传服务器,配置文件也要上传。不太方便。**
现在通过命令行参数传参的形式,根据传入的参数加载 nacos 上对应的配置文件。
首先要先理解 nacos 的使用。其次懂得使用 Go 语言中的 flag 包来解析命令行参数。获取命令行参数的形式有多种,这里只以 flag 包为例。
可以通 flag.String、flag.Int 等等获取对应类型的命令行参数。方法中包含三个字 name、value、usage 分别是参数名、参数值、参数说明. 如果忘记传什么参数可以通过 –help 查看参数说明。
这里以从 nacos 读取配置文件连接 mysql 和 redis 为例浅谈。
话不多说直接上 Demo
1. 打开 nacos 新建一个 demo.yaml 的配置文件
demo:
datasource:
dsn: root:root@tcp(127.0.0.1:3306)/test
showSql: true
redis:
host: 127.0.0.1:6379
password: root
db: 0
2. Demo 程序
var (viperConfig *viper.Viper)
var (nacosIP2 = flag.String("ip", "127.0.0.1", "The nacos of ip address")
port2 = flag.Int("p", 8848, "The nacos of port")
group2 = flag.String("g", "demo", "The nacos of Group")
cfg2 = flag.String("c", "demo.yml", "The path of configuration file")
)
type MysqlConfig struct {
DbDsn string
ShowSQL bool
}
type RedisConfig struct {
RedisAddr string
Password string
RedisDb int
}
func init() {flag.Parse()
}
func main() {ParseRemoteConfig(*nacosIP2, *port2, *group2, *cfg2)
fmt.Println(GetMysqlConfig())
fmt.Println(GetRedisConfig())
}
//ParseRemoteConfig 解析 nacos 配置文件
func ParseRemoteConfig(ip2 string, port2 int, group2 string, cfg2 string) *viper.Viper {viperConfig = viper.New()
viperConfig.SetConfigType("yaml")
viperConfig.SetConfigName(cfg2)
serverConfigs := []constant.ServerConfig{{IpAddr: ip2, Port: uint64(port2)},
}
nacosClient, err := clients.NewConfigClient(vo.NacosClientParam{ClientConfig: &constant.ClientConfig{TimeoutMs: 5000},
ServerConfigs: serverConfigs,
})
if err != nil {logger.OmpLog.Fatal("nacos init failed :", err)
}
content, err := nacosClient.GetConfig(vo.ConfigParam{
DataId: cfg2,
Group: group2,
})
if err != nil {logger.OmpLog.Fatal("read from nacos failed:" + content)
}
viperConfig.ReadConfig(strings.NewReader(content))
return viperConfig
}
//GetMysqlConfig mysql 配置
func GetMysqlConfig() MysqlConfig {
var mc MysqlConfig
mc.DbDsn = viperConfig.GetString("demo.datasource.dsn")
mc.ShowSQL = viperConfig.GetBool("demo.datasource.showSql")
return mc
}
//GetRedisConfig redis 配置
func GetRedisConfig() RedisConfig {
var rrc RedisConfig
rrc.RedisAddr = viperConfig.GetString("demo.redis.host")
rrc.Password = viperConfig.GetString("demo.redis.password")
rrc.RedisDb = viperConfig.GetInt("demo.redis.db")
return rrc
}
执行:
go run main.go -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml
# 或者先编译
go build
./main -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml
即可看到接受到的命令行参数和读取到的配置信息
3. 链接 mysql 和 redis, 修改 main 函数
ParseRemoteConfig(*nacosIP2, *port2, *group2, *cfg2)
// 链接 mysql
db, err := sql.Open("mysql", GetMysqlConfig().DbDsn)
if err != nil {panic(err)
}
err = db.Ping()
if err != nil {panic(err)
}
fmt.Println("mysql connect success...")
// 链接 redis
rdb := redis.NewClient(&redis.Options{Addr: GetRedisConfig().RedisAddr,
Password: GetRedisConfig().Password,
DB: GetRedisConfig().RedisDb,})
ping := rdb.Ping()
err = ping.Err()
if err != nil {panic(err)
}
fmt.Println("redis connect success...")
执行:
go run main.go -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml
# 或者先编译
go build
./main -ip 127.0.0.1 -p 8848 -g demo -c demo.yaml
即可看到数据库和 redis 连接成功
四. 结合之前谈到的 Dockerfile 进行命令行传参
因为部署项目是结合 docker 进行部署的,不可能把代码上传到服务器,去执行 go run 或者 go build。采用 shell 脚本,一键完成自动服务重载。那么就要通过 dockerfile 来将上面的参数传递过来。
这个脚本采用 upx 来帮我们对 go 项目进行打包
#!/usr/bin/env bash
echo " 开始编译文件 "
buildFileName="main"
BuildTime=`date +'%Y.%m.%d.%H:%M:%S'`
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-w -s" -o ${buildFileName}
#go build -o main main.go
echo " 编译完成, 编译时间 ${BuildTime}"
echo " 开始压缩文件 "
upx -9 ${buildFileName}
echo " 完成压缩 "
Dcokerfile
FROM golang:1.17.2-alpine
# 设置工作目录
WORKDIR /root/demo
# 添加可执行文件
ADD ./main $WORKDIR
# 添加
ADD config /root/omp-go/omp-router/config
ADD log /root/omp-go/omp-router/log
# 声明服务端口
EXPOSE 9999
# 启动容器时运行的命令
ENTRYPOINT ["./demo", "-ip","127.0.0.1","-p","8848","-g","demo","-c","demo.yml"]
start.sh
#! /bin/bash
if [! -f 'main']; then
echo 文件不存在! 待添加的安装包: 'main'
exit
fi
echo "main-demo..."
sleep 3
docker stop main-demo
sleep 2
docker rm main-demo
docker rmi main-demo
echo ""
echo "main-demo packing..."
sleep 3
docker build -t main-demo .
echo ""
echo "main-demo running..."
sleep 3
docker run --name main-demo \
-p 9804:9804 \
-d main-demo \
docker logs -f main-demo | sed '/Started main-demoApplication/q'
echo ""
先进行打包,然后启动即可 …