需求:服务启动时,监听的ip,port是可动态配置的(项目含有一个配置文件,可在配置文件中配置ip,port)
动态配置的逻辑是:
main是执行程序,在使用时不更改源码,main从配置文件config中读取host和port,即要使用服务的电脑在启动服务之前就把host和port设置好,访问路径即为host:port/hello,host和port传参到main的run函数里,实现动态配置。
一般来说,启动服务的时候,不会把监听的ip,端口写死在代码里,不然换了物理机还要改代码,这是不可容忍的。所以一个server都会跟着一个config配置文件,保存一些可动态配置的东西。这个服务启动的时候,监听的是哪个端口就需要从一个配置文件里读取出来。
上代码(项目结构参考上一篇博客)
/conf/base.yaml
# conf/base.yaml
service:
redis:
host: 192.168.80.140
port: 8081
/src/dynamic_config/dynamic_config.go
// src/dynamic_config/dynamic_config.go
package dynamic_config
import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
var GlobalConfig *viper.Viper
func init() {
fmt.Printf("Loading configuration logics...\n")
GlobalConfig = initConfig()
go dynamicConfig()
}
func initConfig() *viper.Viper {
GlobalConfig := viper.New()
GlobalConfig.SetConfigName("base")
GlobalConfig.AddConfigPath("conf/")
GlobalConfig.SetConfigType("yaml")
err := GlobalConfig.ReadInConfig()
if err != nil {
fmt.Printf("Failed to get the configuration.")
}
return GlobalConfig
}
func dynamicConfig() {
GlobalConfig.WatchConfig()
GlobalConfig.OnConfigChange(func(event fsnotify.Event) {
fmt.Printf("Detect config change: %s \n", event.String())
})
}
/main.go
// main.go
package main
import (
"gin/src/dynamic_config"
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
gin.SetMode(gin.ReleaseMode)
host := dynamic_config.GlobalConfig.GetString("service.redis.host")
port := dynamic_config.GlobalConfig.GetString("service.redis.port")
way := host + ":" + port
// fmt.Println(way)
r := gin.Default()
r.GET("/hello", func(context *gin.Context) {
context.JSON(
200, gin.H{
"message": "Hello,go web!",
})
})
r.Run(way)
// 原处理:将ip port写死
// r.Run("192.168.80.140:9090)
}
这里的host和port即是从配置文件中读取到的,连接成way即为项目启动的路径。
原代码中访问路径把host和port都写死了,不能实现动态配置的效果。