<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          美團面試:如何設(shè)計一個注冊中心?

          共 2747字,需瀏覽 6分鐘

           ·

          2022-01-01 15:21

          ?
          ?今天,給大家分享如何設(shè)計一個注冊中心
          不管是出于面試,還是深入學習注冊中心,關(guān)于如何設(shè)計一個注冊中心都是一個很好的話題。
          假設(shè)現(xiàn)在我們系統(tǒng)有兩個小系統(tǒng):
          • 訂單系統(tǒng)
          • 商品系統(tǒng)
          單個系統(tǒng)分別部署在不同服務(wù)器上,如果我們訂單系統(tǒng)需要調(diào)用商品系統(tǒng)的某個服務(wù):


          怎么調(diào)用?

          方法1:商品系統(tǒng)開發(fā)的朋友告訴你對應(yīng)的地址。


          方法2:商品系統(tǒng)開發(fā)的朋友把對應(yīng)API地址存放到某個地方。


          方法3:直接通過Nginx,使用域名進行轉(zhuǎn)發(fā)到某個實例上。


          這時候,訂單系統(tǒng)就可以通過上述方法調(diào)用商品系統(tǒng)的API了。

          問題來了

          實際線上環(huán)境中,很少是單體機構(gòu)的,很多都是做了集群的,也就是說每個服務(wù)會有N個實例,少則幾個幾十個,多則幾百上千上萬。如果此時我們還用上面三種方法,當我們的商品系統(tǒng)某個服務(wù)下線(宕機了),或者新增實例,此時是非常的頭疼。
          所以,注冊中心就來了。

          注冊中心來了

          我們能不能搞一個第三方的節(jié)點,這個節(jié)點就用來存放我們商品系統(tǒng)的服務(wù)信息,這樣一來,其他系統(tǒng)需要服務(wù)信息,直接去第三方節(jié)點上去獲取即可。此時,其他系統(tǒng)只要知道這個第三方的節(jié)點地址就可以了。這個第三方的節(jié)點,我們也稱之為注冊中心
          下面我們用服務(wù)提供方(商品系統(tǒng))稱之為provider,服務(wù)調(diào)用方(訂單系統(tǒng))我們稱之為consumer。

          如何設(shè)計一個注冊中心

          我們需要解決如下幾個問題:
          • 服務(wù)如何注冊
          • consumer如何知道provider
          • 服務(wù)注冊中心如何高可用
          • 服務(wù)上下線,消費端如何動態(tài)感知
          服務(wù)注冊


          當我們把服務(wù)信息注冊上去后,就應(yīng)該是:


          服務(wù)列表保存通常有三種方式:本地內(nèi)存、數(shù)據(jù)庫、第三方緩存系統(tǒng)
          注冊上去后,consumer需要服務(wù)地址的時候,就可以用相應(yīng)key去注冊中心獲取對應(yīng)的服務(wù)列表。


          同一個服務(wù)注冊中心,我們可以注冊多個服務(wù),比如用戶服務(wù)、商品服務(wù)、訂單服務(wù)...
          服務(wù)消費


          consumer端通過key獲取指定的服務(wù)地址列表。
          以上的還是蠻簡單的吧,簡單來說,我們就是引用了一個第三方的服務(wù)來存放我們的服務(wù)提供者列表。并且以key-value的形式存儲,key我們可以理解為服務(wù)名稱,value就是服務(wù)實例列表。


          注冊中心高可用
          高可用無非就是做集群,我們可以對注冊中心部署多個節(jié)點。在消費端consumer只需要知道一個服務(wù)注冊中心集群地址cluster-url即可。


          動態(tài)感知服務(wù)上下線
          consumer拿到服務(wù)列表后,會把服務(wù)列表保存起來,保存到本地緩存里。


          consumer通過一定的負載均衡算法,選擇出一個地址,最后發(fā)起遠程的調(diào)用。


          如果我們的服務(wù)節(jié)點掛掉一個了,怎么辦?


          此時,服務(wù)注冊中心的服務(wù)列表還是之前的列表,如果consumer調(diào)用到過掉的節(jié)點上,那豈不是會出問題呀。
          所以,我們的服務(wù)注冊中心需要知道哪個服務(wù)節(jié)點掛了,然后從對應(yīng)服務(wù)列表里刪除。
          有種辦法叫做心跳檢測heartBeat,即就是服務(wù)注冊中心,每隔一定時間去監(jiān)測一下provider,如果監(jiān)測到某個服務(wù)掛了,那就把對應(yīng)服務(wù)地址從服務(wù)列表中刪除。
          根據(jù)心跳檢測,來提出無效服務(wù)。


          可是不對呀,此時consumer端本地列表里還有過掉的服務(wù)地址,怎么辦呢?
          或者是,在增加一個新的服務(wù)節(jié)點


          對于服務(wù)注冊中心來說,就是服務(wù)列表里增加一個服務(wù)地址。
          但是在消費端存在同樣的問題,就是服務(wù)注冊中心的服務(wù)列表和consumer端的服務(wù)列表不一樣了。
          如何讓consumer端也動態(tài)感知呢?
          其實很簡單,此時,我們得思維換一下,因為consumer的服務(wù)列表是來自于服務(wù)注冊中心,我們就可以把consumer理解為消費端,服務(wù)注冊中心理解為服務(wù)端。此時,consumer端就可以去服務(wù)端(服務(wù)注冊中心)拉取provider服務(wù)列表。
          通常有兩種方案:push和pull
          • push:服務(wù)注冊中心主動推送服務(wù)列表給consumer。
          • pull:consumer主動從注冊中心拉取服務(wù)列表。


          不管是push還是pull,都會存在consumer和服務(wù)注冊中心的通信管道。如果他們之間斷開了,那就無法獲取服務(wù)列表了。
          還有就是服務(wù)注冊中心知道consumer的地址,比如
          我得知道你的微信好友,不然我怎么把我手里的資源發(fā)給你
          我們的網(wǎng)絡(luò)通信,必然會存在監(jiān)聽的動作。
          如果服務(wù)注冊中心要push到consumer,此時他們之間需要建立一個會話,所以,在服務(wù)注冊中心會維護一個會話管理的模塊。還有一種方式就是consumer提供一個API,這個API給服務(wù)注冊中心進行回調(diào)。
          本質(zhì)是我們是使用HTTP協(xié)議還是使用Socket監(jiān)聽
          push有個不好點,那就是服務(wù)注冊中心需要維護大量的會話,而且還需要對每個會話維持一個心跳,一遍知曉這些會話狀態(tài),得確保這些consumer能收到數(shù)據(jù),
          另外就是pull,pull其實就相對push就簡單多了。pull和我們前面說的心跳機制是類似的,consumer端啟動定時任務(wù),每個多久拉取服務(wù)注冊中心的服務(wù)列表。pull也不需要去維護大量的會話,我只需要每隔多久調(diào)用接口拉取服務(wù)列表即可。但是這里還是會存在一個問題,因為是定時去拉取,所以會存在一定的數(shù)據(jù)延遲,比如consumer剛剛拉取服務(wù)列表,但就在拉取結(jié)束的后,某個服務(wù)provider掛了,consumer就要等下次拉取才知道對應(yīng)服務(wù)provider掛了。
          如果定時任務(wù)是每隔30秒拉去一次,那就是說,延遲最長時間是30秒。
          還有一種方式long-pull,也叫長輪詢,是上面兩種方案的優(yōu)化方案,consumer發(fā)起拉取請求時,先把這個請求hold住,當服務(wù)注冊中心有發(fā)生變化后,consumer端能立馬感知。
          關(guān)于長輪詢:
          與簡單輪詢相似,只是在服務(wù)端在沒有新的返回數(shù)據(jù)情況下不會立即響應(yīng),而會掛起,直到有數(shù)據(jù)或即將超時
          優(yōu)點:實現(xiàn)也不復(fù)雜,同時相對輪詢,節(jié)約帶寬
          缺點:還是存在占用服務(wù)端資源的問題,雖然及時性比輪詢要高,但是會在沒有數(shù)據(jù)的時候在服務(wù)端掛起,所以會一直占用服務(wù)端資源,處理能力變少
          應(yīng)用:一些早期的對及時性有一些要求的應(yīng)用:web IM 聊天
          這樣,我們就搞定了所謂的服務(wù)上下線動態(tài)感知。
          通過上面的服務(wù)注冊、服務(wù)消費、注冊中心高可用以及動態(tài)感知服務(wù)的上下線,這就是我們?nèi)崿F(xiàn)一個服務(wù)注冊中心的通用模型。
          小總結(jié)
          關(guān)于如何設(shè)計一個注冊中心,無非重點關(guān)以下幾點:
          • 服務(wù)是如何注冊
          • 消費端如何獲取服務(wù)
          • 如何保證注冊中心的高可用
          • 動態(tài)感知服務(wù)的上下線

          有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號


          好文章,我在看??

          ?
          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91啪啪啪网站 | 蜜芽成人在线视频 | feifeibebe | 91夜夜操 | 小黄片免费观看 |