原文發佈在博客mysql
在開發中,咱們須要面對各類各樣的環境,開發環境、測試環境、生產環境……git
而且,各個環境的參數和配置各不相同,好比數據庫鏈接,服務器配置等。咱們怎樣在不一樣環境中調用正確的配置?github
經過配置文件redis
這是一種常見的思路,經過建立多個配置文件,但根據命名區分,好比開發環境爲develop-app.conf,測試環境爲testing-app.conf,生產環境爲production-app.confsql
咱們經過在系統中設置環境變量export ENV_MODE=develop等等。在讀取配置文件時,根據環境變量讀取響應的配置文件。數據庫
這個方式易於使用,深得你們喜好。但這個方案在集羣擴大的必定程度時,會遇到一下幾個主要問題:json
假若有30~40個微服務須要鏈接數據庫運行,這個量級在中小型團隊中很常見了,若是咱們須要更改數據庫密碼,咱們不得不將數十個project逐個進行更新,很是不靈活。安全
代碼與配置摻雜在一塊兒,代碼是許多開發人員均可以看到的,也很容易泄露,而生產環境的各類祕鑰應該只有少數人有權限能看到。這對系統的安全有重大影響。服務器
對於大量相同的配置(好比數據庫配置),邏輯上咱們應該存放在同一個地方,保證只有惟一可靠的數據來源。app
對於這些問題,咱們認爲配置應該集中化管理。
集中化管理帶來如下好處:
最簡單的方案就是存儲在redis中。KV的存儲方式自然適合關聯配置文件。但要完整的使用整個方案,須要作一些準備。
集中式配置管理
咱們的基本思路是:將配置文件的值替換爲佔位符,在系統啓動時,相應的工具將根據佔位符到redis中查詢到實際的值,替換回配置文件。
最初的配置文件是這樣:
{ "database_host":"127.0.0.1", "database_port":3306 }
如今咱們的配置文件變成了這樣:
{ "database_host":"{{redis_hget "global.mysql" "host"}}", "database_port":{{redis_hget "global.mysql" "port"}} }
讀取配置
在啓動時,咱們經過這個工具:https://github.com/gogap/env_json
這樣讀取配置文件
func main() { data, _ := ioutil.ReadFile("./db.conf") dbConf := DBConfig{} if err := env_json.Unmarshal(data, &dbConf); err != nil { fmt.Print(err) return } fmt.Println(dbConf) }
這個工具,默認從/etv/env_string.conf讀取redis的配置信息,固然你能夠更改,更多細節參看說明文檔。
在這個過程當中,env_json首先會從/etv/env_string.conf讀取到redis的配置信息。
典型的/etv/env_string.conf內容以下
{ "storages": [{ "engine": "redis", "options": { "db": 0, "password": "", "pool_size": 10, "address": "127.0.0.1:6379" } }] }
鏈接上redis後,以上面的例子來講,將執行hget global.mysql host以及hget global.mysql port,將取到的值經過模板替換,更新到配置文件中,獲得一個正常的json文本,剩下的就是經過json庫把json內容解碼到結構體中。
到目前爲止,咱們實現了從redis中讀取並替換配置,那麼咱們寫入配置的時候呢?
假如咱們有數十個服務,咱們難道須要逐個去redis中設置嗎?咱們怎樣把這個流程自動化?
寫入配置
咱們須要另外一個工具:env_sync
咱們存儲配置文件實際上是一個具體的git工程,好比開發環境是develop_env,生產環境是production_env,開發人員均可以編輯develop_env這個工程,少數人能夠編輯production_env。
工程裏的內容什麼呢?
咱們約定了這樣的目錄結構
develop_env global.mysql //this is folder data //this is file components.accounts data
在工程中,有一系列的文件夾,文件夾中有一個叫data的文件。這樣的目錄結構會被env_sync識別到,並轉化成一系列的redis命令。
假如global.mysql文件夾下的data文件內容是
{ "host":"127.0.0.1", "port":3306 }
轉化出來的命令是:
hset global.mysql host 127.0.0.1 hset global.mysql port 3306
此過程與讀取過程正好相反,一樣的,env_sync也是從/etc/env_strings.conf讀取配置信息。與讀取工具保持了統一。
總結
總體來看咱們須要作幾個工做
再結合自動化部署工具,每次配置文件有更新時,咱們就在線上環境自動同步到redis。
更多
還有一種需求時,配置文件會動態變化,而咱們不想重啓服務就讀取到配置文件,那你須要https://github.com/gogap/redconf
這個工具能夠實現對redis中數據的檢測,若是數據發生變化,會觸發回調,應用能夠獲得變化先後的值。