Discovery:B站服務(wù)注冊(cè)與發(fā)現(xiàn)

時(shí)間是河流

如果時(shí)間是一條河流,那么歷史就是無(wú)數(shù)的浪花,佇立在河岸回眸,常常有意識(shí)的想要改變某一朵浪花。

2015年中,一群少年為愛(ài)發(fā)電來(lái)到B站,創(chuàng)建了一個(gè)項(xiàng)目,并寫下了第一行Go代碼。這個(gè)項(xiàng)目后來(lái)成為了B站微服務(wù)、中間件及各類平臺(tái)的孵化器,服務(wù)注冊(cè)與發(fā)現(xiàn)模塊也應(yīng)運(yùn)而生。

時(shí)間回溯到2010年11月,zookeeper正式成為Apache的頂級(jí)項(xiàng)目,標(biāo)志著它是工業(yè)級(jí)的成熟穩(wěn)定產(chǎn)品。再到2015年,etcd剛剛發(fā)布了2.0版本,consul才初出茅廬,我們自然而然的選擇了zookeeper作為我們的服務(wù)注冊(cè)與發(fā)現(xiàn)組件。

魔改net/rpc,我們實(shí)現(xiàn)了性能優(yōu)化 鏈路追蹤trace 鑒權(quán) 超時(shí)傳遞 數(shù)據(jù)采集監(jiān)控 等功能,再加上zookeeper,我們還實(shí)現(xiàn)了net/rpc server服務(wù)注冊(cè) net/rpc client服務(wù)發(fā)現(xiàn) 負(fù)載均衡等功能。

這套框架支撐我們度過(guò)了業(yè)務(wù)快速迭代和頻繁改造的階段,但時(shí)間這條河流奔騰不息,轉(zhuǎn)眼進(jìn)入了2018年。

當(dāng)我們佇立河畔,回首日新月異的新潮技術(shù)變更,凝視一路跌跌撞撞濺起的浪花時(shí),在服務(wù)注冊(cè)與發(fā)現(xiàn)領(lǐng)域,我們已經(jīng)落后了。

落后就要挨打

伴隨B站業(yè)務(wù)的快速發(fā)展,微服務(wù)的節(jié)點(diǎn)數(shù)量幾乎指數(shù)級(jí)增長(zhǎng)。zookeeper逐漸在下面的場(chǎng)景不堪重負(fù):

大量長(zhǎng)連接及session探活,已經(jīng)支撐不了辣么高TPS
CP系統(tǒng),當(dāng)機(jī)房間腦裂后不可用
沒(méi)有專家,出問(wèn)題全靠運(yùn)維三寶:重啟、重裝、換機(jī)器

于是,我們調(diào)研了已經(jīng)成熟的etcd、consul、eureka等流行的服務(wù)注冊(cè)與發(fā)現(xiàn)系統(tǒng),經(jīng)過(guò)一番橫向?qū)Ρ戎螅裱?注冊(cè)中心不能因?yàn)樽陨淼娜魏卧蚱茐姆?wù)之間本身的可連通性,我們選擇了AP系統(tǒng)eureka。

但我們團(tuán)隊(duì)整體都是Go技術(shù)棧,eureka在部署及維護(hù)上讓我們覺(jué)得有些不夠得心應(yīng)手,并且以下幾點(diǎn)在eureka1.0版本中也是已知存在的問(wèn)題:

靠輪詢拉取節(jié)點(diǎn),無(wú)法及時(shí)通知
客戶端拉取全量節(jié)點(diǎn),無(wú)法按需獲取
eureka服務(wù)間數(shù)據(jù)同步隨著業(yè)務(wù)節(jié)點(diǎn)數(shù)增加而成倍增加
沒(méi)有完善的日志支撐節(jié)點(diǎn)變更過(guò)程查詢
沒(méi)有管理面板管理節(jié)點(diǎn)

針對(duì)以上問(wèn)題,eureka官方也推出了2.0版本計(jì)劃,但不幸的是停止開(kāi)發(fā)了(幸虧我們選擇了自研,不然就被坑了

所以,我們決定基于eureka的機(jī)制,打造屬于B站的服務(wù)注冊(cè)與發(fā)現(xiàn)系統(tǒng):Discovery

Discovery

時(shí)間進(jìn)入2018,我們也順應(yīng)技術(shù)的大潮,打造了基于k8s的PAAS平臺(tái),大量的業(yè)務(wù)在準(zhǔn)備和正在遷入。我們制定準(zhǔn)入規(guī)范,將業(yè)務(wù)標(biāo)識(shí)appid、容器啟動(dòng)行為entrypoint、服務(wù)的healthcheck等等進(jìn)行了統(tǒng)一。

最關(guān)鍵的,我們需要統(tǒng)一服務(wù)注冊(cè)!

Discovery在這個(gè)大背景下應(yīng)運(yùn)而生,設(shè)計(jì)之初,我們與運(yùn)維童鞋討論了很多細(xì)節(jié),最終拍定以下設(shè)計(jì)目標(biāo):

實(shí)現(xiàn)AP服務(wù)注冊(cè)與發(fā)現(xiàn)系統(tǒng),保證數(shù)據(jù)最終一致性
與PAAS平臺(tái)結(jié)合,多種發(fā)布方式的自動(dòng)服務(wù)注冊(cè)
網(wǎng)絡(luò)閃斷時(shí)服務(wù)可開(kāi)啟自我保護(hù),保證健康的服務(wù)可用
實(shí)現(xiàn)各個(gè)語(yǔ)言sdk,基于HTTP協(xié)議保證交互簡(jiǎn)易

基本抽象

在Discovery中我們以appid作為服務(wù)的標(biāo)識(shí),以hostname定位實(shí)例instance。定義了三種角色server provider consumer,分別代表:

角色 功能
server Discovery服務(wù)節(jié)點(diǎn),提供存儲(chǔ)實(shí)例信息、檢查和剔除無(wú)效節(jié)點(diǎn)、自我保護(hù)等功能
provider 服務(wù)提供者,提供包括注冊(cè)register、30s周期心跳renew、取消注冊(cè)cancel等功能
consumer 服務(wù)消費(fèi)者,基于appid獲取所需服務(wù)的節(jié)點(diǎn)信息,并可選30s周期的長(zhǎng)輪詢監(jiān)聽(tīng)服務(wù)及時(shí)變更狀態(tài)通知
instance 存儲(chǔ)在discovery內(nèi)的實(shí)例信息抽象對(duì)象,包含appid hostname addrs metadata等信息
架構(gòu)圖
基本邏輯
provider

provider啟動(dòng)后會(huì)請(qǐng)求Discovery的register接口進(jìn)行實(shí)例信息注冊(cè),注冊(cè)成功后要進(jìn)行30s周期一次的renew心跳,用于維護(hù)Discovery內(nèi)在線狀態(tài)。

consumer

consumer啟動(dòng)后請(qǐng)求Discovery的fetch接口,根據(jù)appid獲取所有的實(shí)例信息。如果有實(shí)時(shí)接收appid變更的需要,可以請(qǐng)求poll接口進(jìn)行長(zhǎng)輪詢,首次請(qǐng)求會(huì)拿到server節(jié)點(diǎn)下發(fā)的latestTimestamp(表示appid的最后變更時(shí)間,該時(shí)間為server自身時(shí)間且不server間同步)。當(dāng)再有變更發(fā)生時(shí)Discovery更新自身latestTimestamp,與consumer請(qǐng)求時(shí)攜帶的latestTimestamp對(duì)比,如超過(guò)則下發(fā)最新實(shí)例信息,否則維持長(zhǎng)輪詢連接直到30s超時(shí)或有變更發(fā)生。

discovery-server

server開(kāi)始會(huì)收到appid的某一個(gè)實(shí)例的注冊(cè)請(qǐng)求,在內(nèi)存中存儲(chǔ)為instance,通過(guò)Peer to Peer將數(shù)據(jù)同步給其他server節(jié)點(diǎn),之后實(shí)例會(huì)進(jìn)行每30s一次的renew心跳請(qǐng)求,并經(jīng)過(guò)LB后打給任意一個(gè)server節(jié)點(diǎn),節(jié)點(diǎn)間再通過(guò)P2P進(jìn)行數(shù)據(jù)同步,每次renew都會(huì)更新server內(nèi)instancerenewTimestamp時(shí)間戳。當(dāng)該實(shí)例發(fā)送cancel取消注冊(cè)請(qǐng)求后,server節(jié)點(diǎn)將從內(nèi)存中將該instance信息刪除。

server運(yùn)行期間則會(huì)進(jìn)行每90s一個(gè)周期的心跳請(qǐng)求檢測(cè),當(dāng)90s周期內(nèi)某一instance最近一次的renewTimestamp比當(dāng)前時(shí)間小于90s,則判斷該instance失效并刪除。為了避免網(wǎng)絡(luò)故障而導(dǎo)致90s內(nèi)大量instance全無(wú)心跳被全部刪除的情況,server內(nèi)還會(huì)進(jìn)行每60s周期一次的自我保護(hù)判斷,當(dāng) (60s內(nèi)收集的所有心跳數(shù)) 小于 (所有instance的總數(shù)*2*0.85) 時(shí)進(jìn)入自我保護(hù)模式,此時(shí)每90s的刪除檢測(cè)會(huì)無(wú)效,否則取消自我保護(hù),恢復(fù)正常模式。而為了避免確實(shí)有大量節(jié)點(diǎn)突然掛掉(或其他異常情況)而觸發(fā)進(jìn)入自我保護(hù)模式但無(wú)法恢復(fù)為正常模式的情況,設(shè)置了最大自我保護(hù)時(shí)間2h,當(dāng)超過(guò)2h還處于自我保護(hù)模式,則自動(dòng)恢復(fù)為正常模式。

重要邏輯
  1. 復(fù)制(Peer to Peer),數(shù)據(jù)一致性的保障:
    • appid注冊(cè)時(shí)根據(jù)當(dāng)前時(shí)間生成dirtyTimestamp,Discovery的serverAserverB同步(register)時(shí),serverB可能有以下兩種情況:
      • 返回-404serverA攜帶dirtyTimestampserverB發(fā)起注冊(cè)請(qǐng)求,把最新信息同步:
        1. serverB中不存在實(shí)例
        2. serverBdirtyTimestamp較小
      • 返回-409 serverB不同意采納serverA信息,且返回自身信息,serverA使用該信息更新自身
    • appid注冊(cè)成功后,provider每30s發(fā)起一次renew請(qǐng)求,處理流程同上
  2. instance管理
    • 正常檢測(cè)模式,隨機(jī)分批踢掉無(wú)心跳instance節(jié)點(diǎn),盡量避免單應(yīng)用節(jié)點(diǎn)被一次全踢
    • 網(wǎng)絡(luò)閃斷和分區(qū)時(shí)自我保護(hù)模式
      • 60s內(nèi)丟失大量(小于instance總數(shù)*2*0.85)心跳數(shù),“好”“壞”instance信息都保留
      • 所有server都會(huì)持續(xù)提供服務(wù),單個(gè)server的注冊(cè)和發(fā)現(xiàn)功能不受影響
      • 最大保護(hù)時(shí)間,防止分區(qū)恢復(fù)后大量原先instance真的已經(jīng)不存在時(shí),一直處于保護(hù)模式
  3. consumer客戶端
    • 長(zhǎng)輪詢+server推送,服務(wù)發(fā)現(xiàn)準(zhǔn)實(shí)時(shí)
    • 訂閱式,只需要關(guān)注想要關(guān)注的appidinstance列表變化
    • 緩存實(shí)例instance列表信息,保證與server網(wǎng)絡(luò)不通等無(wú)法訪問(wèn)到server情況時(shí)原先的instance可用
特別注意

server間同步復(fù)制是需要時(shí)間的,那如何保證consumer請(qǐng)求serverB時(shí),因?yàn)閿y帶的latestTimestamp是來(lái)自serverA,但serverB晚于該次請(qǐng)求才收到同步事件,而導(dǎo)致獲取的節(jié)點(diǎn)信息不一致?

我們通過(guò)consumer啟動(dòng)后,從nodes接口獲取到Discovery的所有server節(jié)點(diǎn)后,隨機(jī)選取一個(gè)serverA進(jìn)行fetch poll等請(qǐng)求,保證在consumer生命周期內(nèi),實(shí)例信息和時(shí)間信息始終來(lái)自同一個(gè)serverA。除非遇到網(wǎng)絡(luò)等錯(cuò)誤才切換節(jié)點(diǎn)到serverB并清空latestTimestamp,再當(dāng)做首次請(qǐng)求重新拉取appid的全部實(shí)例信息和時(shí)間信息。

多注冊(cè)中心

Discovery的同步復(fù)制機(jī)制天生好支持多注冊(cè)中心。

我們用zone來(lái)表示機(jī)房,假設(shè)zoneAzoneB的Discovery集群之間要相互同步,那我們只需要將zoneA當(dāng)做zoneB的特殊server節(jié)點(diǎn),同理將zoneB當(dāng)做zoneA特殊server節(jié)點(diǎn)。

當(dāng)zoneAserverA收到appid1的注冊(cè)請(qǐng)求,并同步給內(nèi)部的其他server后,再同步給server-zoneB,zoneB即可復(fù)制到appid1的實(shí)例信息。

zoneB內(nèi)部server間同步后不再需要同步回zoneA,所以特殊server就是指在發(fā)送同步請(qǐng)求時(shí),判斷該請(qǐng)求是否來(lái)自相同的zone,是的話就像zoneA同步給zoneB,否的話就像zoneB內(nèi)部同步后不再向其他zone同步。

注:zoneAzoneB間,建議使用SLB進(jìn)行負(fù)載均衡

與PAAS在一起

我們的PAAS平臺(tái)已經(jīng)集成了Discovery的服務(wù)注冊(cè),也就是provider能力。業(yè)務(wù)只需要正常發(fā)布就可以直接注冊(cè)到Discovery,并依賴pod的生命周期進(jìn)行renew心跳請(qǐng)求管理。

如果服務(wù)需要提供RPC、集群、權(quán)重等自定義信息,則只需要暴露 /register 接口并返回map[string]string格式的json數(shù)據(jù),PAAS在啟動(dòng)實(shí)例后和注冊(cè)信息前,通過(guò)回調(diào)該接口獲取信息,將信息作為metedata同時(shí)注冊(cè)到Discovery。

基于此,依賴服務(wù)(consumer)就可以獲取到實(shí)例信息,并對(duì)服務(wù)進(jìn)行訪問(wèn)。

管理節(jié)點(diǎn)

我們還實(shí)現(xiàn)了簡(jiǎn)單的管理能力,可以基于appid環(huán)境信息獲取到所有實(shí)例信息。并基于此擴(kuò)展了查詢依賴服務(wù) 生成CPU和內(nèi)存profile圖 火焰圖等功能。

奔騰不息的河流

當(dāng)我們?cè)僖淮蝸辛⒃诤影痘仨?,發(fā)現(xiàn)時(shí)光的浪花翻騰,但總有那么幾朵浪花丑陋,讓人想要在今后扔石子時(shí),扔的漂亮~

結(jié)語(yǔ)

Discovery已經(jīng)服務(wù)于B站幾萬(wàn)+的實(shí)例規(guī)模,通過(guò)借此總結(jié)我們?cè)诜?wù)注冊(cè)與發(fā)現(xiàn)領(lǐng)域的實(shí)踐經(jīng)驗(yàn),希望對(duì)業(yè)界閱讀此文的童鞋能夠有所幫助和啟發(fā)。同時(shí),我們也希望收到大家的反饋意見(jiàn),詳情請(qǐng)看Discovery開(kāi)源項(xiàng)目【點(diǎn)我到Github】。

本文作者:冠冠愛(ài)看書

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • あくどい 1[顏色]過(guò)于濃艷,[味道]太膩。(色などがくどくて、いやな感じだ)。 あくどい色 刺眼的顏色 あくどい...
    嬌靨如花閱讀 709評(píng)論 0 0
  • 成功真的來(lái)的不簡(jiǎn)單,因?yàn)樾枰掷m(xù)的重復(fù)的練習(xí)。舒適區(qū)一學(xué)習(xí)區(qū)一恐慌區(qū)。天才來(lái)自刻意的練習(xí),不斷的重復(fù)做一件事。這個(gè)...
    快樂(lè)三人行閱讀 235評(píng)論 0 0
  • 你知道嗎? 荔枝,自己剝的,跟別人給你剝的,味道是不一樣的,荔枝的果肉雖然很柔軟,很甜美,但,它的外表卻很粗糙,...
    等一個(gè)人咖啡nan閱讀 276評(píng)論 2 1
  • 沒(méi)有了夏日的烈陽(yáng) 沒(méi)有了女兒的叛逆 沒(méi)有了繁瑣的羈絆 父親,就這樣與世界之吻,打破了現(xiàn)實(shí)的一切,離了一切,不過(guò)是另...
    為也閱讀 240評(píng)論 0 0
  • 有些人,就在身旁,你卻感到陌生 尋尋覓覓,越尋越遠(yuǎn) 別無(wú)選擇,一個(gè)人行走
    澤蔓碧落閱讀 147評(píng)論 0 0

友情鏈接更多精彩內(nèi)容