1. 程式人生 > >zookeeperclient代碼解讀

zookeeperclient代碼解讀

dap hashtable send search san 分布式系統 ora 回調數據 term

近期一直在忙WebPageTest(下面簡稱wpt)開源庫的改動工作,當中一項工作須要將zookeeper(下面簡稱zk)集成到wpt裏。

zk作為分布式系統的同步工具。實現了寫的原子性(要麽失敗。要麽成功,並不存在寫一半的情況),並通過“選舉組長“和”重選組長“,在負載均衡的同一時候保證數據一致性。關於zk服務端的設計,能夠參考官網http://zookeeper.apache.org/。

本文闡述zkclient的實現,一來能夠梳理下思路,二來也可作為閱讀筆記。

zkclient代碼比較少。全然採用C語言來實現。包含:


1、hashtable的實現

hashtable的實現。包含hashtable.h。hashtable.c,hashtable_itr.h和hashtable_itr.c。從代碼中能夠看到,hashtable的方式基本是依照JAVA中的hash表實現的。進一步講,hash表的內部實現事實上非常easy,如圖所看到的:

技術分享

hashtable內部保存了多個鏈表(數量可變。當當前節點數超過指定負載時添加)。元素插入。改動,刪除時都以hash key為唯一主鍵,換言之最重要的就是保證hash key的唯一性。元素插入時,hashtable依據key計算出index。並依據index選擇將元素插入第幾個鏈表。比方:假設key計算出index為1,那麽元素就被插入到list2中;假設當前負載超過最大額度。hashtable自己主動擴展鏈表數並對各個鏈表中的節點又一次hash。

hashtable_itr.h和hashtable_itr.c是hashtable的叠代器,實際上是直接對hashtable中的某個鏈表進行叠代。


2、序列化和反序列化

zk自己實現了序列化,整體而言,zk傳輸的網絡數據都是:包長度(網絡大端形式)+包內容。oarchive結構體和iarchive分別包括序列化和反序列化的函數指針,這些函數指針包括最主要的操作,如(反)序列化int,long。字符串(vector,buffer,String)。

詳細協議包頭數據(zookeeper.jute.h和zookeeper.jute.c)。則依據詳細數據類型。調用各個基本函數指針完畢。


3、winconfig.h

這裏須要單獨講一下winconfig.h。在講zk繼承到wpt時,我發現編譯報錯HMONITOR__ type redefinition。進一步排查發現與原來是這個文件定義的類型和wpt中相沖突,在各個宏定義之前加上#ifndef推斷之後,編譯成功。


4、核心實現

核心實現中_zhandle封裝zkclient的全部數據,包含zk_adaptor.h,mt_adaptor.c

1)IO線程。

IO線程負責socket的接收或發送。發送時數據被寫入到to_send鏈表。zk隨後通過select或poll完畢。

假設是異步任務(須要回調),則同一時候創建回調並將回調數據增加到sent_requests鏈表。由於zk服務端保證了任務的有序性(順序請求一定也是順序返回)。所以當zk服務端任務結果到來,IO線程將任務結果寫入to_process鏈表中。那麽to_process中的結果和sent_requests中的回調就是相應的。

同步調用和異步調用流程一致,不同的是同步調用沒有回調函數(實際上回調函數被指定為SYNCHRONOUS_MARKER),該標識會導致Complete線程做特殊處理。由於異步流程是沒有等待的,所以同步時函數進入等待狀態(等待任務標記完畢)。

接下來就非常easy了:zk將二者統一發送給Complete線程去處理。我想zk通過順序來確定回調,應該是為了避免在發送數據中記錄回調的信息。

2)Complete線程。Complete線程非常easy,就是IO線程的消費者:調用回調函數。

假設回調函數為SYNCHRONOUS_MARKER。則Complete通知等待線程任務完畢。


zookeeperclient代碼解讀