Gin 动态加载配置文件和优雅重启

Gin 动态加载配置文件和优雅重启

动态加载配置文件

var RootCmd = &cobra.Command{
	Use:   "dressup",
	Short: "operation background",
	Long:  "no only book operation background",
	Run: func(cmd *cobra.Command, args []string) {
		app.Run(NewApp("gon", cmd))
	},
}
func init() {
	RootCmd.Flags().String("db", "configs/db.toml", "the path to databases config file")
	RootCmd.Flags().String("redis", "configs/redis.toml", "the path to redis config file")
	RootCmd.Flags().String("server", "configs/server.toml", "the path to server config file")
}

使用 github.com/BurntSushi/toml映射配置到 struct

confDBFile := b.Command.Flags().Lookup("db")
	if confDBFile == nil {
		panic("there is no configuration file [db]")
	}
	if _, err := toml.DecodeFile(confDBFile.Value.String(), &conf.DBConfig); err != nil {
		panic(err)
	}

	confServerFile := b.Command.Flags().Lookup("server")
	if confServerFile == nil {
		panic("configuration file does not exist:[server]")
	}
	if _, err := toml.DecodeFile(confServerFile.Value.String(), &conf.ServerConfig); err != nil {
		panic(err)
	}
	
	confRedisFile := b.Command.Flags().Lookup("redis")
	if confRedisFile == nil {
		panic("there is no configuration file [redis]")
	}
	if _, err := toml.DecodeFile(confRedisFile.Value.String(), &conf.RedisConfig); err != nil {
		panic(err)
	}
var paths = make([]string, 0)
// 把需要动态加载的配置文件路径写进 []string
paths = append(paths, confDBFile.Value.String())

// 动态加载配置使用goroutine
	go func() {
		err := watchFiles(paths)
		if err != nil {
			return
		}
	}()

func watchFiles(paths []string) error {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}
	defer func(watcher *fsnotify.Watcher) {
		err = watcher.Close()
		if err != nil {
			return
		}
	}(watcher)

	done := make(chan bool)
	go func() {
		for {
			select {
			case event, ok := <-watcher.Events:
				if !ok {
					return
				}
				parts := strings.Split(event.Name, "\\")
				if len(parts) < 1 {
					err = fmt.Errorf("")
				}
				name := strings.Split(parts[len(parts)-1], ".")
				if len(name) == 0 {
					err = fmt.Errorf("")
				}
				if event.Op&fsnotify.Write == fsnotify.Write {
					fmt.Println(fmt.Sprintf("监听到配置文件[%s]发生改变", name[0]))
					switch name[0] {
					case "db":
						if _, err = toml.DecodeFile(event.Name, &conf.DBConfig); err != nil {
							panic(err)
						}
					case "redis":
						if _, err = toml.DecodeFile(event.Name, &conf.RedisConfig); err != nil {
							panic(err)
						}
					}
				}
			case err, ok := <-watcher.Errors:
				if !ok {
					return
				}
				log.Error(err)
			}
		}
	}()

	for _, path := range paths {
		err = watcher.Add(path)

		if err != nil {
			log.Error(err)
		}
	}
	<-done
	return nil
}

配置文件发生变化时

优雅的重启

func (b *Base) Run() {
	// This function is received after the kill command, wait for 5 s
	f := func() error {
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
		select {
		case sig := <-c:
			ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
			defer cancel()
			if err := b.Srv.Shutdown(ctx); err != nil {
				logger.Error(zap.String("shutdown error", zap.Error(err).String))
				return err
			}
			
			return fmt.Errorf("received signal %s", sig)
		}
	}
	logger.Infox("terminated", zap.Error(f()))
	
}

收到退出信号时 至多等待5s 一般5s 一个请求也完成了 不够的话可以修改长一点

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值