【五】golang實戰之配置中心
阿新 • • 發佈:2022-04-08
為什麼需要配置中心
- 新增配置
- 你現在的使用者服務有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格式後,即可啟動
至此,配置中心已經完成