【五】golang实战之配置中心

为什么需要配置中心

  1. 添加配置
    1. 你现在的用户服务有10个部署实例,那么添加配置项你得去十个地方修改配置文件还得重新启动等
    2. 即使go的viper能完成修改配置文件自动生效,那么你得考虑其他语言是否也能做到这点,其他的服务是否也一定会使用viper
  2. 修改配置
    1. 大量的服务可能会使用同一个配置,比如我要更好jwt的secrect,这么多实例需要统一更新
  3. 开发,测试,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

配置

按服务创建命名空间

image-20220319220024361

选择好命名空间后,创建配置文件

image-20220319220047604

将自己的配置按图示填写

image-20220319220133592

同理把user-api的也发布了

image-20220319220154185

读取配置

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进行转换。修改完毕之后如下所示

image-20220319225159390

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格式后,即可启动

image-20220321231623808

至此,配置中心已经完成

posted @ 2022-04-07 23:01  丶吃鱼的猫  阅读(1018)  评论(0编辑  收藏  举报