從配置文件到分布式配置管理QConf

QConf是奇虎360廣泛使用的配置管理服務粒没,現(xiàn)已開源:
https://github.com/Qihoo360/QConf吊档。歡迎大家關(guān)注使用转培。

本文從設計初衷,架構(gòu)實現(xiàn)崭篡,使用情況及相關(guān)產(chǎn)品比較四個方面進行介紹挪哄。

設計初衷

在分布式環(huán)境中,出于負載琉闪、容錯等種種原因迹炼,幾乎所有的服務都需要在不同的機器節(jié)點上部署多個實例。當然颠毙,業(yè)務項目中總少不了各種類型的配置文件斯入,我們常常會遇到這樣的問題,有時僅僅是一個配置內(nèi)容的修改蛀蜜,便需要重新進行代碼提交svn/git刻两,打包,分發(fā)上線的流程滴某。當部署的機器有很多時磅摹,分發(fā)上線本身也是一個很繁雜的工作滋迈。而配置文件的修改頻率又遠遠大于代碼本身。
追本溯源户誓,我們認為所有的這些麻煩的根源是我們對配置和代碼在管理和發(fā)布過程中不加區(qū)分饼灿。配置本身源于代碼,是我們?yōu)榱颂岣叽a的靈活性而提取出來的一些經(jīng)常變化的或需要定制的內(nèi)容帝美,而正是配置的這種天生的變化特征給我們帶了很大的麻煩碍彭。
因此,我們開發(fā)了分布式配置管理系統(tǒng)QConf证舟,并依托QConf在360內(nèi)部提供了一整套配置管理服務硕旗,QConf致力于將配置內(nèi)容從代碼中完全分離出來窗骑,及時可靠高效地提供配置訪問和更新服務女责。

整體認識

為了讓大家對之后的內(nèi)容有個直觀的認識,先來介紹一下如果你要在自己的項目中使用QConf應該怎么做:

  • 首先创译,需要在機器上部署QConf抵知,采用cmake構(gòu)建。

cmake ..
make
make install

  • 之后软族,通過Zookeeper客戶端或QConf管理界面在Zookeeper上建立自己的節(jié)點結(jié)構(gòu)刷喜,節(jié)點完整路徑便是QConf的key值,以360公司內(nèi)部QConf管理界面為例:
    圖1 QConf管理界面
    圖1 QConf管理界面
  • 最后立砸,選擇自己項目的語言版本的QConf庫掖疮,并在需要需要獲得配置內(nèi)容的位置,直接調(diào)用類似于get_conf(key)這樣的接口颗祝,并放心每次取得的都是最新鮮出爐的配置浊闪。以shell命令為例:


    圖2 QConf shell接口使用
    圖2 QConf shell接口使用

需要說明的是,使用QConf后已經(jīng)沒有所謂的配置文件的概念螺戳,你要做的就是在你需要的地方獲取正確的內(nèi)容搁宾,我們認為,這才是你真正想要的倔幼。

架構(gòu)介紹

了解了QConf的設計初衷和使用方式盖腿,相信大家已經(jīng)對QConf有一個整體的認識和對其實現(xiàn)的猜想。在介紹架構(gòu)之前损同,還需要向大家申明一下我們對配置信息的定位翩腐,因為這個定位直接決定了我們的結(jié)構(gòu)設計和組件選擇。

  • 單條數(shù)據(jù)量小
  • 更新頻繁(較代碼而言)
  • 配置總數(shù)可能巨大膏燃,但單臺機器關(guān)心配置數(shù)有限
  • 讀多寫少

進入主題茂卦,開始介紹QConf的架構(gòu)實現(xiàn):


圖3 QConf整體結(jié)構(gòu)
圖3 QConf整體結(jié)構(gòu)

上圖展示的是QConf的基本結(jié)構(gòu),從角色上劃分主要包括QConf客戶端蹄梢,QConf服務端疙筹,QConf管理端富俄。

QConf服務端。

QConf使用ZooKeeper集群作為服務端提供服務而咆。眾所周知霍比,ZooKeeper是一套分布式應用程序協(xié)調(diào)服務,根據(jù)上面提到的對配置內(nèi)容的定位暴备,我們認為可以將單條配置內(nèi)容直接存儲在ZooKeeper的一個ZNode上悠瞬,并利用ZooKeeper的Watch監(jiān)聽功能實現(xiàn)配置變化時對客戶端的及時通知。
按照ZooKeeper的設計目標涯捻,其只提供最基礎的功能浅妆,包括順序一致,原子性障癌,單一系統(tǒng)鏡像凌外,可靠性和及時性。另外Zookeeper還有如下特點:

  • 類文件系統(tǒng)的節(jié)點組織
  • 穩(wěn)定涛浙,無單點問題
  • 訂閱通知機制

關(guān)于Zookeeper康辑,更多見:https://zookeeper.apache.org/

QConf客戶端

但在接口方面,ZooKeeper本身只提供了非辰瘟粒基本的操作疮薇,并且其客戶端接口原始,所以我們需要在QConf的客戶端部分解決如下問題

  • 降低與ZooKeeper的鏈接數(shù)
    原生的ZooKeeper客戶端中我注,所有需要獲取配置的進程都需要與ZooKeeper保持長連接按咒,在生產(chǎn)環(huán)境中每個客戶端機器可能都會有上百個進程需要訪問數(shù)據(jù),這對ZooKeeper的壓力非常大而且也是不必要的但骨。
  • 本地緩存
    當然我們不希望客戶端進程每次需要數(shù)據(jù)都走網(wǎng)絡獲取励七,所以需要維護一份客戶端緩存,僅在配置變化時更新嗽冒。
  • 容錯
    當進程死掉呀伙,網(wǎng)絡終端,機器重啟等異常情況發(fā)生時添坊,我們希望能盡可能的提供可靠的配置獲取服務
  • 多語言版本接口
    目前提供的語言版本包括:c剿另,php,java贬蛙,python雨女,go,lua阳准,shell
  • 配置更新及時氛堕,可以秒級同步到所有客戶端機器
  • 高效的配置讀取,內(nèi)存級的訪問速度

下面來看下QConf客戶端的架構(gòu):


圖4 QConf客戶端架構(gòu)
圖4 QConf客戶端架構(gòu)

可以看到QConf客戶端主要有:agent野蝇、各種語言接口讼稚、連接他們的消息隊列和共享內(nèi)存括儒。
在QConf中,配置以key-value的形式存在锐想,業(yè)務進程給出key獲得對應value帮寻,這與傳統(tǒng)的配置文件方式是一致的。

下面通過兩個主要場景的數(shù)據(jù)流動來說明他們各自的功能和角色:

  • 業(yè)務進程請求數(shù)據(jù)


    圖5 數(shù)據(jù)流動-業(yè)務進程請求數(shù)據(jù)
    圖5 數(shù)據(jù)流動-業(yè)務進程請求數(shù)據(jù)
  1. 業(yè)務進程調(diào)用某一種語言的QConf接口赠摇,從共享內(nèi)存中查找需要的配置信息固逗;
  2. 如果存在,直接獲取藕帜,否則會向消息隊列中加入該配置key烫罩;
  3. agent消息隊列中感知需要獲取的配置key;
  4. agentZooKeeper查詢數(shù)據(jù)并注冊監(jiān)聽洽故;
  5. agent將獲得的配置value序列化后放入共享內(nèi)存贝攒;
  6. 業(yè)務進程從共享內(nèi)存中獲得最新值。
  • 配置信息更新


    圖5 數(shù)據(jù)流動-配置更新
    圖5 數(shù)據(jù)流動-配置更新
  1. ZooKeeper通知agent某配置項發(fā)生變化收津;
  2. agentZooKeeper查詢新值并更新watcher饿这;
  3. agent用新值更新共享內(nèi)存中的該配置項浊伙。

通過上面的說明撞秋,可以看出QConf的整體結(jié)構(gòu)和流程非常簡單。
QConf中各個組件或線程之間僅通過有限的中間數(shù)據(jù)結(jié)構(gòu)通信嚣鄙,耦合性非常小吻贿,各自只負責自己的本職工作和一畝三分地,而不感知整體結(jié)構(gòu)哑子。下面通過幾個點來詳細介紹:

  • 無鎖
    根據(jù)上文提到的配置信息的特征舅列,我們認為在QConf客戶端進行的是多進程并行讀取的過程,對配置數(shù)據(jù)來說讀操作遠多于寫操作卧蜓。為了盡可能的提高讀效率帐要,整個QConf客戶端在操作共享內(nèi)存時采用的是無鎖的操作,同時為了保證數(shù)據(jù)的正確弥奸,采取了如下兩個措施:

  • 單點寫榨惠,將寫操作集中到單一線程,其他線程通過中間數(shù)據(jù)結(jié)構(gòu)與之通信盛霎,寫操作排隊赠橙,用這種方法犧牲掉一些寫效率。在QConf客戶端愤炸,需要對共享內(nèi)存進行寫操作的場景有:

    1. 用戶進程通過消息隊列發(fā)送的需獲取key期揪;
    2. ZooKeeper 配置修改刪除等觸發(fā)Watcher通知,需更新规个;
    3. 為了消除watcher丟失造成的不一致凤薛,需要定時對共享內(nèi)存中的所有配置重新注冊watcher姓建,此時可能會需要更新;
    4. 發(fā)生agent重啟缤苫、網(wǎng)絡中斷引瀑、ZooKeeper會話過期等異常情況之后,需重新拉數(shù)據(jù)榨馁,此時可能需要更新憨栽。
  • 讀驗證,無鎖的讀寫方式翼虫,會存在讀到未寫入完全數(shù)據(jù)的危險屑柔,但考慮到在絕對的讀多寫少環(huán)境中這種情況發(fā)生的概率較低,所以我們允許其發(fā)生珍剑,通過讀操作時的驗證來發(fā)現(xiàn)掸宛。共享內(nèi)存數(shù)據(jù)在序列化時會帶其md5值,業(yè)務進程從共享內(nèi)存中讀取時招拙,利用預存的md5值驗證是否正確讀取唧瘾。

  • 異常處理
    QConf中采取了一些處理來應對不可避免的異常情況

  • 采用父子進程keepalive的方式,應對agent進程異常退出的情況别凤;

  • 維護一份落盤數(shù)據(jù)饰序,應對斷網(wǎng)情況下共享內(nèi)存又被清空的狀況;

  • 網(wǎng)絡中斷恢復后规哪,對共享內(nèi)存中所有數(shù)據(jù)進行檢查求豫,并重新注冊watcher;

  • 定時掃描共享內(nèi)存诉稍;

  • 數(shù)據(jù)序列化
    QConf 客戶端中有多處需要將數(shù)據(jù)序列化通信或存儲蝠嘉,包括共享內(nèi)存,消息隊列杯巨,落盤數(shù)據(jù)中的內(nèi)容蚤告。采取如下協(xié)議:


    圖6 數(shù)據(jù)序列化協(xié)議
    圖6 數(shù)據(jù)序列化協(xié)議
  • agent任務
    通過上面的描述,大家應該大概了解了agent所做的一些事情服爷,下面從agent的內(nèi)部的線程分工的角度整理一下杜恰,如下圖:


    圖7 Agent內(nèi)部結(jié)構(gòu)
    圖7 Agent內(nèi)部結(jié)構(gòu)
  • Send線程:ZooKeeper線程,處理網(wǎng)絡數(shù)據(jù)包层扶,進行協(xié)議包的解析與封裝箫章,并將Zookeeper的事件加入WaitingEvent隊列等待處理;

  • Event 線程:ZooKeeper線程镜会,依次獲取WaitingEvent隊列中的事件檬寂,并進行相應處理,這里我們關(guān)注節(jié)點刪除戳表、節(jié)點值修改桶至、子節(jié)點變化昼伴、會話過期等事件。對特定的事件會進行相應的操作镣屹,以節(jié)點值修改為例圃郊,agent會按上邊提到的方式序列化該節(jié)點key,并將其加入到WaitingWriting隊列女蜈,等待Main線程處理持舆;

  • msq線程:之前講數(shù)據(jù)流動場景的時候有提到,用戶進程從共享內(nèi)存中找不到對應配置后伪窖,會向消息隊列中加入該配置逸寓,Msq線程便是負責從消息隊列中獲取業(yè)務進程的取配置需求,并同樣通過WaitingWriting隊列發(fā)送給Main進程覆山;

  • Scan 線程:掃描共享內(nèi)存中的所有配置竹伸,發(fā)現(xiàn)與Zookeeper不一致的情況時,將key值加入WaitingWriting隊列簇宽。Scan線程會在ZooKeeper重連或輪詢期到達時進行上述操作勋篓;

  • Main線程:共享內(nèi)存的唯一寫入線程,從Zookeeper獲得數(shù)據(jù)寫入共享內(nèi)存魏割,維護共享內(nèi)存中的內(nèi)容譬嚣;

  • Trigger 線程:該線程負責一些周邊邏輯的調(diào)用,包括:

    1. dump操作:將共享內(nèi)存的內(nèi)容同步一份到本地见妒,QConf采用的gdbm孤荣;
    2. feedback操作:QConf支持更新反饋的功能,可向用戶指定web服務以一定的格式發(fā)送反饋须揣;
    3. script操作:在某些情況下,業(yè)務希望當配置變化時钱豁,做一些自定義的操作耻卡,QConf支持配置變化時調(diào)用用戶腳本,agent按一種固定的約定在配置發(fā)生變化時調(diào)用對應的腳本牲尺。

QConf管理端

管理端是業(yè)務修改配置的頁面入口卵酪,利用數(shù)據(jù)庫提供一些如批量導入,權(quán)限管理谤碳,版本控制等上層功能溃卡。
由于公司內(nèi)的一些業(yè)務耦合和需求定制,當前開源的QConf管理端這邊提供了一個簡易的頁面蜒简,和一套下層的c++接口瘸羡,如下圖:


圖8 QConf簡易管理界面
圖8 QConf簡易管理界面

之后計劃進一步完善以及跟社區(qū)合作提供更友好的界面。

QConf的結(jié)構(gòu)及實現(xiàn)大概就介紹到這搓茬,接下來...

One More Thing

QConf 除了存儲配置的基本功能外犹赖,還在公司內(nèi)提供了一套簡單的服務發(fā)現(xiàn)功能队他,該功能允許業(yè)務在QConf上配置一組服務,QConf會監(jiān)控其服務的存活峻村。當業(yè)務進程調(diào)用獲取服務的接口時麸折,會根據(jù)用戶需求,返回全部可用服務粘昨,或某一可用服務垢啼。
不同于普通配置:

  • 結(jié)構(gòu)上多一個Monitor的角色,來監(jiān)控所有服務的存活, 如下圖:


    圖9 提供服務發(fā)現(xiàn)的QConf結(jié)構(gòu)
    圖9 提供服務發(fā)現(xiàn)的QConf結(jié)構(gòu)
  • 提供對應的客戶端接口张肾,get_host獲取某一可用服務膊夹,get_allhost獲取所有可用服務
  • 管理端頁面對應的展示方式及操作,尤其是對指定服務的添加刪除捌浩,上線下線

需要明確的是放刨,目前Monitor事實上僅僅是通過查看服務端口的存活來判斷的,在實際生產(chǎn)環(huán)境中尸饺,該功能多與實際服務提供者的監(jiān)控結(jié)合进统,由服務提供者的監(jiān)控調(diào)用QConf的相應接口實現(xiàn)服務的上下線。

使用方式及使用場景

目前360內(nèi)部已經(jīng)廣泛的使用QConf浪听。覆蓋云盤螟碎、大流程、系統(tǒng)部迹栓、dba掉分、圖搜、影視克伊、地圖酥郭、硬件、手機衛(wèi)士愿吹、好搜等大部分業(yè)務不从。
部署國內(nèi)外共51幾個機房,客戶端機器超兩萬臺犁跪,穩(wěn)定運行兩年椿息。

使用的方式主要包括:

  • 簡單配置
    公司內(nèi)使用最廣泛的用法,QConf非常適合經(jīng)常需要變動的配置使用坷衍,如開關(guān)信息寝优、版本信息、推薦信息枫耳、超時時間等乏矾。
  • 服務方式
    這種方式多被服務提供者采用,如dba,系統(tǒng)部等妻熊,采用上述的服務配置的方式夸浅,通過QConf向公司的所有業(yè)務提供存儲,計算及web服務扔役。

配置管理類產(chǎn)品比較

通過上面的介紹帆喇,大家應該感覺到QConf與puppet,confd這類產(chǎn)品還是有很大不同的亿胸。
國內(nèi)與之類似的產(chǎn)品包括淘寶的diamond坯钦,微博的vintage,百度的disconf侈玄。
其中diamond和vintage比較類似婉刀,他們將配置數(shù)據(jù)存在像mysql或redis這樣的存儲中,并需要通過客戶端的輪訓來感知配置變化序仙,這樣會有很多的無效通訊突颊,因此采取比較md5值的方式來避免整個配置值的傳輸;
disconf與QConf類似潘悼,同樣采用ZooKeeper的通知機制律秃,不同的是,其將真實的配置數(shù)據(jù)存在mysql中治唤,并且整個與java耦合很重棒动,且配置復雜。

QConf因為其對配置信息的定位宾添,使得整個結(jié)構(gòu)非常簡單船惨,容易部署和使用。在Github上可以找到完整代碼:https://github.com/Qihoo360/QConf 歡迎關(guān)注缕陕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末粱锐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子榄檬,更是在濱河造成了極大的恐慌卜范,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹿榜,死亡現(xiàn)場離奇詭異,居然都是意外死亡锦爵,警方通過查閱死者的電腦和手機舱殿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來险掀,“玉大人沪袭,你說我怎么就攤上這事≌燎猓” “怎么了冈绊?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵侠鳄,是天一觀的道長。 經(jīng)常有香客問我死宣,道長伟恶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任毅该,我火速辦了婚禮博秫,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘眶掌。我一直安慰自己挡育,他們只是感情好,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布朴爬。 她就那樣靜靜地躺著即寒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪召噩。 梳的紋絲不亂的頭發(fā)上母赵,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機與錄音蚣常,去河邊找鬼市咽。 笑死,一個胖子當著我的面吹牛抵蚊,可吹牛的內(nèi)容都是我干的施绎。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼贞绳,長吁一口氣:“原來是場噩夢啊……” “哼谷醉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起冈闭,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤俱尼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后萎攒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遇八,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年耍休,在試婚紗的時候發(fā)現(xiàn)自己被綠了刃永。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡羊精,死狀恐怖斯够,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤读规,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布抓督,位于F島的核電站,受9級特大地震影響束亏,放射性物質(zhì)發(fā)生泄漏铃在。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一枪汪、第九天 我趴在偏房一處隱蔽的房頂上張望涌穆。 院中可真熱鬧,春花似錦雀久、人聲如沸宿稀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祝沸。三九已至,卻和暖如春越庇,著一層夾襖步出監(jiān)牢的瞬間罩锐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工卤唉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留涩惑,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓桑驱,卻偏偏與公主長得像竭恬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子熬的,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理痊硕,服務發(fā)現(xiàn),斷路器押框,智...
    卡卡羅2017閱讀 134,716評論 18 139
  • ZooKeeper 分布式過程協(xié)同技術(shù)詳解 簡介 分布式系統(tǒng) 分布式系統(tǒng)是同時跨越多個物理主機, 獨立運行的多個軟...
    魯云飛_閱讀 2,650評論 0 1
  • 從三月份找實習到現(xiàn)在岔绸,面了一些公司,掛了不少橡伞,但最終還是拿到小米盒揉、百度、阿里兑徘、京東预烙、新浪、CVTE道媚、樂視家的研發(fā)崗...
    時芥藍閱讀 42,280評論 11 349
  • 今夜終于起風了。印象中小時候每年都會經(jīng)歷沙塵暴:一到春秋天就刮沙塵,一連持續(xù)好多天最域,風力動輒六七級谴分,冬天就更厲害,...
    美麗豬小窩閱讀 375評論 0 0
  • 別嫌不夠,這7本書夠你讀一陣子了薄翅, 你有沒與這樣的經(jīng)歷沙兰,因為別人書單推薦的很多“經(jīng)典”作品,讀起來晦澀難懂翘魄,而幾乎...
    知讀先生閱讀 1,574評論 2 15