【五】golang实战之配置中心
为什么需要配置中心
- 添加配置
- 你现在的用户服务有10个部署实例,那么添加配置项你得去十个地方修改配置文件还得重新启动等
- 即使go的viper能完成修改配置文件自动生效,那么你得考虑其他语言是否也能做到这点,其他的服务是否也一定会使用viper
- 修改配置
- 大量的服务可能会使用同一个配置,比如我要更好jwt的secrect,这么多实例需要统一更新
- 开发,测试,uat以及生产环境如何隔离
配置中心可以帮助我们解决以上问题,不需要手动更改每个实例的配置文件,并且能够快速方便的读取到配置文件在线更新。
安装
docker run --name nacos-standalone -e MODE=standalone -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m -p 8848:8848 -d nacos/nacos-server:latest
访问需要http://192.168.0.102:8848/nacos/index.html,不能不带后面的nacos/index.html,账号和密码为nacos和nacos
配置
按服务创建命名空间
选择好命名空间后,创建配置文件
将自己的配置按图示填写
同理把user-api的也发布了
读取配置
user-service
改造之前的配置结构体,添加json的tag,方便后面的解析
type DBConfig struct {
Username string `mapstructure:"username" json:"username"`
Password string `mapstructure:"password" json:"password"`
Host string `mapstructure:"host" json:"host"`
Port int `mapstructure:"port" json:"port"`
Dbname string `mapstructure:"dbname" json:"dbname"`
DefaultStringSize int `mapstructure:"defaultStringSize" json:"defaultStringSize"`
MaxIdleConn int `mapstructure:"maxIdleConn" json:"maxIdleConn"`
MaxOpenConn int `mapstructure:"maxOpenConn" json:"maxOpenConn"`
}
type LogConfig struct {
LogPath string `mapstructure:"logPath" json:"logPath"`
MaxSize int `mapstructure:"maxSize" json:"maxSize"`
MaxBackups int `mapstructure:"maxBackups" json:"maxBackups"`
MaxAge int `mapstructure:"maxAge" json:"maxAge"`
Level string `mapstructure:"level" json:"level"`
}
type ServiceConfig struct {
Host string `mapstructure:"host" json:"host"`
Port int `mapstructure:"port" json:"port"`
Name string `mapstructure:"name" json:"name"`
Id string `mapstructure:"id" json:"id"`
Tags string `mapstructure:"tags" json:"tags"`
}
type ConsulConfig struct {
Host string `mapstructure:"host" json:"host"`
Port int `mapstructure:"port" json:"port"`
}
type NacosConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
User string `mapstructure:"user"`
Password string `mapstructure:"password"`
DataId string `mapstructure:"dataId"`
Namespace string `mapstructure:"namespace"`
Group string `mapstructure:"group"`
Timeout int `mapstructure:"timeout"`
LogLevel string `mapstructure:"logLevel"`
LogPath string `mapstructure:"logPath"`
CachePath string `mapstructure:"cachePath"`
}
单独定义一个nacos的配置文件
var (
DB *gorm.DB
Config *ServerTO
NacosConfig *models.NacosConfig
)
type ServerTO struct {
DBConfig *models.DBConfig `mapstructure:"db" json:"db"`
Log *models.LogConfig `mapstructure:"log" json:"log"`
Service *models.ServiceConfig `mapstructure:"service" json:"service"`
Consul *models.ConsulConfig `mapstructure:"consul" json:"consul"`
}
func init() {
Config = &ServerTO{
DBConfig: &models.DBConfig{},
Log: &models.LogConfig{},
Service: &models.ServiceConfig{},
Consul: &models.ConsulConfig{},
}
NacosConfig = &models.NacosConfig{}
}
修改配置文件
nacos:
host: xx.xx.xx.xx
port: xxx
DataId: xxx
Namespace: xxxxxxxxxxxx
Group: xx
Timeout: xxx
LogLevel: xxx
cachePath: xx/xx/xx
logPath: xx/xx/xx
修改读取配置文件的函数
func InitConfig() {
vp := viper.New()
vp.AddConfigPath("configs/")
vp.SetConfigName("config")
vp.SetConfigType("yml")
err := vp.ReadInConfig()
if err != nil {
panic(any(fmt.Sprintf("Read config failed:%v", err)))
}
err = vp.UnmarshalKey("nacos", &global.NacosConfig)
if err != nil {
panic(any(fmt.Sprintf("Read nacos failed:%v", err)))
}
sc := []constant.ServerConfig{
{
IpAddr: global.NacosConfig.Host,
Port: uint64(global.NacosConfig.Port),
ContextPath: "/nacos",
},
}
cc := constant.ClientConfig{
NamespaceId: global.NacosConfig.Namespace,
TimeoutMs: uint64(global.NacosConfig.Timeout),
NotLoadCacheAtStart: true,
LogDir: global.NacosConfig.LogPath,
CacheDir: global.NacosConfig.CachePath,
LogLevel: global.NacosConfig.LogLevel,
}
configClient, err := clients.CreateConfigClient(map[string]interface{}{
"serverConfigs": sc, "clientConfig": cc,
})
if err != nil {
panic(any(err))
}
content, err := configClient.GetConfig(vo.ConfigParam{
DataId: global.NacosConfig.DataId,
Group: global.NacosConfig.Group,
})
if err != nil {
panic(any(err))
}
err = json.Unmarshal([]byte(content), &global.Config)
if err != nil {
panic(any(fmt.Sprintf("Read config failed:%v", err)))
}
}
另外,需要将nacos中的配置文件由yaml转为json,可以通过https://www.json2yaml.com/convert-yaml-to-json进行转换。修改完毕之后如下所示
user-api
修改global文件,除nacos之外的配置结构体添加json的tag
package global
import user "imooc/mxshop-api/api/user/v0"
var (
Config *ServerConfig
Nacos *NacosConfig
UserClient user.UserServiceClient
)
type LogConfig struct {
LogPath string `mapstructure:"logPath" json:"logPath"`
MaxSize int `mapstructure:"maxSize" json:"maxSize"`
MaxBackups int `mapstructure:"maxBackups" json:"maxBackups"`
MaxAge int `mapstructure:"maxAge" json:"maxAge"`
Level string `mapstructure:"level" json:"level"`
}
type ServiceConfig struct {
Host string `mapstructure:"host" json:"host"`
Port int `mapstructure:"port" json:"port"`
Name string `mapstructure:"name" json:"name"`
}
type JwtConfig struct {
SigningKey string `mapstructure:"key" json:"key"`
Expire int `mapstructure:"expire" json:"expire"`
}
type RedisConfig struct {
Host string `mapstructure:"host" json:"host"`
Port int `mapstructure:"port" json:"port"`
}
type SmsConfig struct {
Template string `mapstructure:"code" json:"code"`
Key string `mapstructure:"key" json:"key"`
Secret string `mapstructure:"secret" json:"secret"`
Expire int `mapstructure:"expire" json:"expire"`
Domain string `mapstructure:"domain" json:"domain"`
Region string `mapstructure:"region" json:"region"`
Name string `mapstructure:"name" json:"name"`
Version string `mapstructure:"version" json:"version"`
}
type ConsulConfig struct {
Host string `mapstructure:"host" json:"host"`
Port int `mapstructure:"port" json:"port"`
}
type ServerConfig struct {
Log *LogConfig `mapstructure:"log" json:"log"`
Service *ServiceConfig `mapstructure:"service" json:"service"`
UserService *ServiceConfig `mapstructure:"user-service" json:"user-service"`
Jwt *JwtConfig `mapstructure:"jwt" json:"jwt"`
Sms *SmsConfig `mapstructure:"sms" json:"sms"`
Redis *RedisConfig `mapstructure:"redis" json:"redis"`
}
func init() {
Config = &ServerConfig{
Log: &LogConfig{},
Service: &ServiceConfig{},
UserService: &ServiceConfig{},
Jwt: &JwtConfig{},
Sms: &SmsConfig{},
Redis: &RedisConfig{},
Consul: &ConsulConfig{},
}
Nacos = &NacosConfig{}
}
修改配置文件
nacos:
host: xx.xx.xx.xx
port: xxx
DataId: xxx
Namespace: xxxxxxxxxxxx
Group: xx
Timeout: xxx
LogLevel: xxx
cachePath: xx/xx/xx
logPath: xx/xx/xx
修改读取配置文件的函数
vp := viper.New()
vp.AddConfigPath("configs/")
vp.SetConfigName("config")
vp.SetConfigType("yml")
err := vp.ReadInConfig()
if err != nil {
panic(any(fmt.Sprintf("Read configs failed:%v", err.Error())))
}
err = vp.UnmarshalKey("nacos", &global.Nacos)
if err != nil {
panic(any(fmt.Sprintf("Read nacos configs failed:%v", err)))
}
sc := []constant.ServerConfig{
{
IpAddr: global.Nacos.Host,
Port: uint64(global.Nacos.Port),
ContextPath: "/nacos",
},
}
cc := constant.ClientConfig{
NamespaceId: global.Nacos.Namespace,
TimeoutMs: uint64(global.Nacos.Timeout),
NotLoadCacheAtStart: true,
LogDir: global.Nacos.LogPath,
CacheDir: global.Nacos.CachePath,
LogLevel: global.Nacos.LogLevel,
}
configClient, err := clients.CreateConfigClient(map[string]interface{}{
"serverConfigs": sc, "clientConfig": cc,
})
if err != nil {
panic(any(err))
}
content, err := configClient.GetConfig(vo.ConfigParam{
DataId: global.Nacos.DataId,
Group: global.Nacos.Group,
})
if err != nil {
panic(any(err))
}
err = json.Unmarshal([]byte(content), &global.Config)
if err != nil {
panic(any(fmt.Sprintf("Read config failed:%v", err)))
}
修改main函数
host, port, err := utils.FilterServiceByName(global.Config.UserService.Name)
if err != nil {
zap.S().Fatalw("FilterServiceByName", "name", global.Config.UserService.Name, "err", err)
return
}
zap.S().Infof("init user-service at %s:%d", host, port)
userConn := initialize.InitUserConnection(host, port)
defer func() {
if err := userConn.Close(); err != nil {
panic(err.(any))
}
}()
global.UserClient = user.NewUserServiceClient(userConn)
zap.S().Info("user-api running...")
addr := fmt.Sprintf("%s:%d", global.Config.Service.Host, global.Config.Service.Port)
将涉及到的配置修改的地方一一修改,然后将nacos中的配置格式更改为json格式后,即可启动
至此,配置中心已经完成
作者:丶吃鱼的猫
出处:https://www.cnblogs.com/eatfishcat/p/16114799.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出, 原文链接 如有问题, 可站内留言咨询.