Golang 中可以像 Laravel 一样实时更新 Config 变量吗?

背景#

近期重构 PHP 项目为 Golang 时遇到这样一个问题,看看大佬们有没有遇到过,或更加优秀的办法。

我们需要给系统建立一个配置表,存储一些常用但不经常改动的配置(需要改动),如存:smtp 信息、是否开启审核、是否 xxx、等(运营人员可以改动)。

白话说:这个表类似于 CMS\WordPress 后台系统,能改某些配置文件。

旧项目实现#

旧项目 PHP 代码如下实现,在初始化时,将配置表数据直接写入 config 中,由于语言特性,config 可做到实时更新。(数据库更新)
Golang 中可以像 Laravel 一样实时更新 Config 变量吗?

新项目实现#

我们考虑了两种方案实现:

  1. 在 Golang 中我们使用的是 Gin 框架,考虑存在 Redis 中,每次获取的时候实时去读,但在获取多个配置时要多次去从 Redis 获取,浪费多次网络请求,且后台管理系统更新也不太方便;
  2. 由程序员去配置,写到配置文件中,每次更改都需要程序员去发版改动配置文件;

理想中的逻辑#

我们希望配置像 PHP 一样,修改数据库配置表后,能够写到一个全局函数或变量中(存在内存中),后台管理系统修改,业务逻辑可以全局函数或变量中在直接获取。

目前没有想到合适的方法实现,大家有类似的方法吗?

讨论数量: 15

用 github.com/spf13/viper ,用配置中心驱动。或者就是直接用配置文件,用它带的文件变化事件实时更新配置

1周前 评论
陈大剩 (楼主) 1周前
deatil (作者) 1周前
唐章明 1周前
deatil (作者) 1周前
  • 可以监听某个信号,收到信号后重新 load 配置文件,后面的请求就是新的配置。

file

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

type Config struct {
    AppName string
}

func main() {
    cfg := &Config{"App1"}
    fmt.Printf("PID: %d\n", os.Getpid())
    go func() {
        for {
            time.Sleep(time.Second * 3)
            fmt.Println(cfg.AppName)
        }
    }()
    var ch = make(chan os.Signal)
    signal.Notify(ch, syscall.SIGUSR2)
    for s := range ch {
        if s == syscall.SIGUSR2 {
            cfg.AppName = "App2"
            // todo reload config
        }
    }
}
  • 还可以用一个接口来更新全局变量的值,这个全局变量存储你的配置
1周前 评论
陈大剩 (楼主) 1周前

你不如存到数据库,然后缓存一份到内存里,用的时候优先读缓存,缓存没有读数据库,更新的时候存到数据库顺便把缓存的也更新了,省得你读 redis 也耗时间,改起来也方便,重启了数据也还在

1周前 评论
陈大剩 (楼主) 1周前
陈大剩 (楼主) 1周前

如果你是文件的话,可以使用这个库:github.com/fsnotify/fsnotifyfsnotify.NewWatcher() 会 初始化一个 Watcher 它可以监听文件的变化,做到配置的及时更新

如果你是通过管理后台管理配置的话,那么建议 ETCD,我们之前就是使用 ETCD 搭建的配置中心,然后通过 ETCD 一键推送配置至测试环境、灰度环境、线上环境

1周前 评论

还不如保留 config 表的能力到 golang 上面去,修改 / 删除更新下缓存即可。

1周前 评论
陈大剩 (楼主) 1周前

这要是 Java,直接上配置中心就行了,何必用这个了

1周前 评论