Go语言实现配置热加载的方法分享
作者:tracy小猫 时间:2024-02-07 04:02:47
概述
web项目,经常需要热启动各种各样的配置信息,一旦这些服务发生变更,我们需要重新启动web server,以使配置生效,实现配置热加载。这里有几种方法实现这个需求。
go 定时器协程实现
项目结构
首先来看一下整个项目的目录结构:
- dyconfig // 项目地址
- config // 配置文件目录
- api.yaml // 采用yaml格式文件
- global // 代码文件夹
- config
- config_define
- init
- reload
- go.mod // go package管理依赖的包文件
- go.sum // go package管理打包产生的文件
- main.go // web server的入口,主函数
代码细节
接下来依次看一下各文件的主体内容:
conf/api.yaml文件定义了配置项,包含server的host及port信息。
service:
server:
env: dev
host: 127.0.0.1
port: 9902
global/init.go
package global
import (
"context"
"path"
)
type Config struct {
Conf struct {
FilePath string
LastModifyTime int64
}
ctx context.Context
cancel context.CancelFunc
}
func NewConfig() (*Config, error) {
conf := new(Config)
conf.ctx, conf.cancel = context.WithCancel(context.Background())
conf.Conf.FilePath = path.Join("./config", "api.yaml")
APIconfig = conf.loadRoute()
go conf.reload() //开启协程监听routeNotify
go func() {
for {
select {
case lastModifyTime, ok := <-routeNotify:
if !ok {
return
}
conf.Conf.LastModifyTime = lastModifyTime
route := routeAtomic.Load().(*APIConf)
if route != nil {
APIconfig = route
}
}
}
}()
return conf, nil
}
func (c *Config) Stop() {
c.cancel()
}
定义Config 根据LastModifyTime 判断是否有发生变化,FilePath为文件路径
go conf.reload()
开启协程监听routeNotify,routeNotify内容是文件修改时间的timestamp
global/reload.go
package global
import (
"fmt"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
"sync/atomic"
"time"
)
const (
CheckInterval = 5 * time.Second
)
var (
routeAtomic atomic.Value //原子性,解决并发问题
routeNotify = make(chan int64) //channel 放入timestamp
)
func (c *Config) reload() {
ticker := time.NewTicker(CheckInterval)
defer ticker.Stop()
for {
select {
case <-c.ctx.Done():
close(routeNotify)
return
case <-ticker.C:
if f, err := os.Stat(c.Route.FilePath); err != nil {
fmt.Println(err)
} else if f.ModTime().Unix() != c.Route.LastModifyTime {
if c.Route.LastModifyTime == 0 {
c.Route.LastModifyTime = f.ModTime().Unix()
} else {
routeAtomic.Store(c.loadConfig())
routeNotify <- f.ModTime().Unix()
fmt.Println("配置文件发生变化")
}
}
}
}
}
func (c *Config) loadConfig() *APIConf {
if fp, err := ioutil.ReadFile(c.Route.FilePath); err != nil {
fmt.Println(err)
return nil
} else {
route := new(APIConf)
if err := yaml.Unmarshal(fp, &route); err != nil {
return nil
}
return route
}
}
定时器监听文件的修改时间与LastModifyTime是否相同,如果不同,则
package global
var (
APIconfig = new(APIConf)
)
package global
type ServiceConf struct {
Server struct {
Env string `yaml:"env"`
Host string `yaml:"host"`
Port string `yaml:"port"`
} `yaml:"server"`
}
type APIConf struct {
Service ServiceConf `yaml:"service"`
}
mian
package main
import (
"dyconfig/global"
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
if conf, err := global.NewConfig(); err != nil { // 初始化配置
fmt.Println(err)
} else {
defer conf.Stop()
}
gin.SetMode(gin.DebugMode)
r := gin.Default()
r.GET("/ping", func(context *gin.Context) {
fmt.Println("当前host是: ", global.APIconfig.Service.Server.Host)
fmt.Println("当前port是: ", global.APIconfig.Service.Server.Port)
context.JSON(
200, gin.H{
"host": global.APIconfig.Service.Server.Host,
"port": &global.APIconfig.Service.Server.Port,
})
})
port := global.APIconfig.Service.Server.Port
fmt.Println("当前host是: ", global.APIconfig.Service.Server.Host)
fmt.Println("当前port是: ", global.APIconfig.Service.Server.Port)
port = ":" + port
_ = r.Run(port)
}
调用示例
1.第一次调用,port为9902
2. 修改config ,port为9903
来源:https://juejin.cn/post/7185563516094316600
标签:Go,配置,热加载
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性
2022-08-13 22:06:58
![](https://img.aspxhome.com/file/2023/0/97540_0s.png)
python3爬虫中多线程进行解锁操作实例
2021-04-29 00:16:42
![](https://img.aspxhome.com/file/2023/6/117426_0s.png)
JS与Ajax Get和Post在使用上的区别实例详解
2024-04-23 09:07:40
vscode配置远程开发与免密登录的技巧
2023-04-29 02:43:41
![](https://img.aspxhome.com/file/2023/3/132403_0s.png)
[翻译]网页设计中的模式窗口
2009-05-29 18:00:00
![](https://img.aspxhome.com/file/UploadPic/20095/29/376600_124350365243zv-44s.jpg)
python实现textrank关键词提取
2021-11-01 16:47:58
SQL Server异常代码处理的深入讲解
2024-01-22 11:42:58
![](https://img.aspxhome.com/file/2023/8/119258_0s.png)
IDEA中使用Git拉取代码时报 Git pull failed原因及解决方法
2022-10-01 21:28:36
![](https://img.aspxhome.com/file/2023/5/132415_0s.png)
浅谈python中的@以及@在tensorflow中的作用说明
2021-06-10 01:50:22
pandas object格式转float64格式的方法
2022-05-26 15:58:53
opencv python图像梯度实例详解
2021-05-17 23:26:30
![](https://img.aspxhome.com/file/2023/2/124692_0s.png)
浅谈PYTHON 关于文件的操作
2022-06-07 19:54:58
Python利用Pillow(PIL)库实现验证码图片的全过程
2022-05-18 21:27:47
![](https://img.aspxhome.com/file/2023/7/81457_0s.png)
python实现TCP服务器端与客户端的方法详解
2023-05-17 09:39:39
在Golang中执行Shell命令的教程详解
2024-04-25 15:10:51
![](https://img.aspxhome.com/file/2023/6/134186_0s.png)
vue+element-ui+sortable.js实现表格拖拽功能
2024-04-09 11:00:11
![](https://img.aspxhome.com/file/2023/0/139720_0s.gif)
Vue3 计算属性的用法详解
2024-04-28 09:20:33
![](https://img.aspxhome.com/file/2023/3/133113_0s.gif)
python编程测试电脑开启最大线程数实例代码
2023-07-07 12:19:46
![](https://img.aspxhome.com/file/2023/9/101449_0s.png)
学会这个炫酷图表利器pyecharts,还怕不被公司重用?
2023-01-16 23:33:39
![](https://img.aspxhome.com/file/2023/4/124234_0s.png)
python 实时遍历日志文件
2021-03-30 09:26:20