Golang 實(shí)現(xiàn) Zookeeper 循環(huán)監(jiān)聽

前言

Zookeeper作為一種應(yīng)用協(xié)調(diào)系統(tǒng)兆沙,有著廣泛的應(yīng)用诚些,其中一種就是作為服務(wù)注冊中心,比如:Zookeeper+Dubbo+Spring實(shí)現(xiàn)服務(wù)注冊與發(fā)現(xiàn)氢哮。

目前袋毙,遇到了這樣一個(gè)問題,用Go語言編寫的服務(wù)A冗尤,依賴于Zookeeper實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)與注冊听盖,Master選舉胀溺,資源分配等功能。這些功能很大程度上依賴于對Zookeeper節(jié)點(diǎn)監(jiān)聽的操作皆看,監(jiān)聽要具有實(shí)時(shí)性和穩(wěn)定性仓坞,并要針對go-zookeeper——封裝了Zookeeper操作的API做優(yōu)化,實(shí)現(xiàn)對Zookeeper的永久監(jiān)聽功能腰吟。

本文以Master選舉為例无埃,實(shí)現(xiàn)對Zookeeper的/master下屬子節(jié)點(diǎn)的循環(huán)監(jiān)聽

go-zookeeper監(jiān)聽分析

Master節(jié)點(diǎn)只能有一個(gè),在api中毛雇,我們發(fā)現(xiàn)ChildrenW可以滿足對/master子節(jié)點(diǎn)監(jiān)聽的需求

// 1. 返回通道
func (c *Conn) ChildrenW(path string) ([]string, *Stat, <-chan Event, error) {
    if err := validatePath(path, false); err != nil {
        return nil, nil, nil, err
    }

    var ech <-chan Event
    res := &getChildren2Response{}
    _, err := c.request(opGetChildren2, &getChildren2Request{Path: path, Watch: true}, res, func(req *request, res *responseHeader, err error) {
        if err == nil {
            ech = c.addWatcher(path, watchTypeChild)
        }
    })
    if err != nil {
        return nil, nil, nil, err
    }
    return res.Children, &res.Stat, ech, err
}

func (c *Conn) addWatcher(path string, watchType watchType) <-chan Event {
    c.watchersLock.Lock()
    defer c.watchersLock.Unlock()

    // 2. 通道大小為1
    ch := make(chan Event, 1)
    wpt := watchPathType{path, watchType}
    c.watchers[wpt] = append(c.watchers[wpt], ch)
    return ch
}

在源碼中我們可以看到

  1. ChildrenW會(huì)返回一個(gè)通道嫉称,這個(gè)通道用來傳遞節(jié)點(diǎn)監(jiān)聽的結(jié)果,結(jié)果類型為Event

  2. 通道大小為1灵疮,且每調(diào)用一次ChildrenW就會(huì)創(chuàng)建一個(gè)通道织阅,故監(jiān)聽只能生效一次

  3. 我們需要自定義函數(shù),用來接收Event傳遞而來的結(jié)果震捣,這個(gè)函數(shù)必然是異步的

如果我們想實(shí)現(xiàn)循環(huán)監(jiān)聽

  1. 就要不斷的循環(huán)ChildrenW和他的Event響應(yīng)函數(shù)

  2. 這兩者還都是異步的荔棉,因?yàn)橐WC監(jiān)聽的實(shí)時(shí)性,在接收到Event后要立即異步開啟新的ChildrenW和其響應(yīng)函數(shù)

如果簡單的使用循環(huán)與協(xié)程可能會(huì)導(dǎo)致

  1. 代碼丑陋

  2. 會(huì)開啟大量協(xié)程

  3. 無法控制協(xié)程執(zhí)行順序蒿赢,導(dǎo)致程序運(yùn)行結(jié)果異常

循環(huán)監(jiān)聽

// 使用專屬通道接收event
// 通道大小由服務(wù)并發(fā)量決定润樱,越大處理越快
MasterChan = make(chan zk.Event, 1)

// zookeeper master節(jié)點(diǎn)監(jiān)聽函數(shù),需要異步調(diào)用
func masterObserver(conn *zk.Conn, path string) {
    // 開啟event響應(yīng)協(xié)程
    go masterChanProcess(conn)
    for {
        _, _, event, err := conn.ChildrenW(path)
        if err != nil {
            log.Printf("Start to watch children path %s failed, err: %s", path, err.Error())
        }
        log.Printf("Start to watch children path %s successful!", path)

        select {
        case e := <-event:
            // 將監(jiān)聽得到的event放入其專屬通道內(nèi)
            MasterChan <- e
        }
    }
}

// event響應(yīng)函數(shù)羡棵,需要異步調(diào)用
func masterChanProcess(conn *zk.Conn) {
    for {
        select {
        // 專屬通道響應(yīng)
        case event := <-MasterChan:
            log.Printf("Master alteration has been detected, path is %s", event.Path)
            /** event響應(yīng)過程祥国,your code */
        }
    }
}

func main() {
    // zk初始化
    go masterChanProcess(conn)
}

優(yōu)點(diǎn)

  1. 僅開啟兩個(gè)協(xié)程,資源消耗小

  2. 通道保證高并發(fā)性能晾腔,以及event的響應(yīng)順序

  3. 代碼簡潔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舌稀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子灼擂,更是在濱河造成了極大的恐慌壁查,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剔应,死亡現(xiàn)場離奇詭異睡腿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)峻贮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門席怪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纤控,你說我怎么就攤上這事挂捻。” “怎么了船万?”我有些...
    開封第一講書人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵刻撒,是天一觀的道長骨田。 經(jīng)常有香客問我,道長声怔,這世上最難降的妖魔是什么态贤? 我笑而不...
    開封第一講書人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮醋火,結(jié)果婚禮上悠汽,老公的妹妹穿的比我還像新娘。我一直安慰自己芥驳,他們只是感情好介粘,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著晚树,像睡著了一般。 火紅的嫁衣襯著肌膚如雪雅采。 梳的紋絲不亂的頭發(fā)上爵憎,一...
    開封第一講書人閱讀 50,050評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音婚瓜,去河邊找鬼宝鼓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛巴刻,可吹牛的內(nèi)容都是我干的愚铡。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼胡陪,長吁一口氣:“原來是場噩夢啊……” “哼沥寥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起柠座,我...
    開封第一講書人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬榮一對情侶失蹤邑雅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后妈经,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淮野,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年吹泡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了骤星。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡爆哑,死狀恐怖洞难,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情揭朝,我是刑警寧澤廊营,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布歪泳,位于F島的核電站,受9級(jí)特大地震影響露筒,放射性物質(zhì)發(fā)生泄漏呐伞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一慎式、第九天 我趴在偏房一處隱蔽的房頂上張望伶氢。 院中可真熱鬧,春花似錦瘪吏、人聲如沸癣防。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蕾盯。三九已至,卻和暖如春蓝丙,著一層夾襖步出監(jiān)牢的瞬間级遭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來泰國打工渺尘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挫鸽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓鸥跟,卻偏偏與公主長得像丢郊,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子医咨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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