golang配置文件熱更新

配置文件熱更新是服務(wù)器程序的一個(gè)基本功能浓瞪,通過(guò)熱更新可以不停機(jī)調(diào)整程序的配置英岭,特別是在生產(chǎn)環(huán)境可以提供極大的便利荧库,比如發(fā)現(xiàn)log打得太多了可以動(dòng)態(tài)調(diào)高日志等級(jí),業(yè)務(wù)邏輯參數(shù)變化,甚至某個(gè)功能模塊的開(kāi)關(guān)等都可以動(dòng)態(tài)調(diào)整科乎。

每種語(yǔ)言都有自己的熱更新實(shí)現(xiàn)方式空闲,在golang里面我看到了有人采用了一種錯(cuò)誤的實(shí)現(xiàn)方式,如下:

type Config struct {
    Test1 string `json:"Test1"`
    Test2 int `json:"Test2"`
}

var (
    config *Config
)

func loadConfig() {
    f, err := ioutil.ReadFile("config.json")
    if err != nil {
        fmt.Println("load config error: ", err)
    }
    err = json.Unmarshal(f, &config)
    if err != nil {
        fmt.Println("Para config failed: ", err)
    }

}
func init() {
    loadConfig()
    fmt.Println("Load config: ", *config)
    s := make(chan os.Signal, 1)
    signal.Notify(s, syscall.SIGUSR2)
    go func() {
        for {
            <-s
            loadConfig()
            fmt.Println("ReLoad config: ", *config)
        }
    }()

}

這種方式片迅,的問(wèn)題就在于config可能被多個(gè)routine同時(shí)訪問(wèn)空免,那么loadcofig的時(shí)候直接在config上做解析是有問(wèn)題的蹋砚。在上面例子中析恢,還是用的最簡(jiǎn)單的json配置,如果是其他更復(fù)雜的配置形式,如xml亏拉,需要自己寫解析函數(shù)(而不是一個(gè)json.Unmarshal)的時(shí)候更容易放大問(wèn)題专筷。

可以采用更新的時(shí)候?qū)onfig加鎖來(lái)解決這個(gè)問(wèn)題:

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "os/signal"
    "sync"
    "syscall"
)

//用json配置測(cè)試
type Config struct {
    Test1 string `json:"Test1:`
    Test2 int    `json:"Test1:`
}

var (
    config     *Config
    configLock = new(sync.RWMutex)
)

func loadConfig() bool {
    f, err := ioutil.ReadFile("config.json")
    if err != nil {
        fmt.Println("load config error: ", err)
        return false
    }

    //不同的配置規(guī)則溪烤,解析復(fù)雜度不同
    temp := new(Config)
    err = json.Unmarshal(f, &config)
    if err != nil {
        fmt.Println("Para config failed: ", err)
        return false
    }

    configLock.Lock()
    config = temp
    configLock.Unlock()
    return true
}

func GetConfig() *Config {
    configLock.RLock()
    defer configLock.RUnlock()
    return config
}

func init() {
    if !loadConfig() {
        os.Exit(1)
    }

    //熱更新配置可能有多種觸發(fā)方式檬嘀,這里使用系統(tǒng)信號(hào)量sigusr1實(shí)現(xiàn)
    s := make(chan os.Signal, 1)
    signal.Notify(s, syscall.SIGUSR1)
    go func() {
        for {
            <-s
            log.Println("Reloaded config:", loadConfig())
        }
    }()
}

func main() {
    select {}
}

因?yàn)闊峒虞d的時(shí)候鸳兽,可能有很多未知的routine在使用config揍异,通過(guò)切換配置的時(shí)候加鎖可以保證多個(gè)routine對(duì)config的正確操作,不過(guò)需要注意的是戚嗅,獲取配置文件的時(shí)候也需要加鎖替久。

在sync/atomic包里稼锅,還真看到了一個(gè)利用原子操作動(dòng)態(tài)更新配置文件的方案: https://golang.org/pkg/sync/atomic/
測(cè)試使用后感覺(jué)不錯(cuò)锥债,實(shí)現(xiàn)原理如下:

var config Value // holds current server configuration
// Create initial config value and store into config.
config.Store(loadConfig())
go func() {
        // Reload config every 10 seconds
        // and update config value with the new version.
        for {
                time.Sleep(10 * time.Second)
                config.Store(loadConfig())
        }
}()
// Create worker goroutines that handle incoming requests
// using the latest config value.
for i := 0; i < 10; i++ {
        go func() {
                for r := range requests() {
                        c := config.Load()
                        // Handle request r using config c.
                        _, _ = r, c
                }
        }()
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市看疗,隨后出現(xiàn)的幾起案子沙峻,更是在濱河造成了極大的恐慌,老刑警劉巖鹃觉,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件专酗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡盗扇,警方通過(guò)查閱死者的電腦和手機(jī)祷肯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)疗隶,“玉大人,你說(shuō)我怎么就攤上這事蒋纬。” “怎么了碾阁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵愁茁,是天一觀的道長(zhǎng)嘶居。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任盗飒,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梨州。我一直安慰自己,他們只是感情好帮掉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布盅称。 她就那樣靜靜地躺著,像睡著了一般疾层。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上湖饱,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼港柜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛授舟,可吹牛的內(nèi)容都是我干的擎淤。 我是一名探鬼主播桩盲,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼柬姚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼穴店!你這毒婦竟也來(lái)了忧风?” 一聲冷哼從身側(cè)響起该窗,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后贪绘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體亿虽,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡攻走,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了此再。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昔搂。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖引润,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情议慰,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布拍霜,位于F島的核電站越驻,受9級(jí)特大地震影響换途,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜速种,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望低千。 院中可真熱鬧配阵,春花似錦、人聲如沸示血。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)难审。三九已至瘫拣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間告喊,已是汗流浹背麸拄。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工派昧, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人拢切。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓蒂萎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親淮椰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岖是,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容