微服務4:服務註冊與發現
1 微服務的註冊與發現
我們前面在全景架構中對服務註冊與發現做了大致的說明,本章我們著重詳細說明微服務下注冊與發現的這個能力。
微服務註冊與發現類似於生活中的"電話通訊錄"的概念,它記錄了通訊錄服務和電話的對映關係。在分散式架構中,服務會註冊進去,當服務需要呼叫其它服務時,就這裡找到服務的地址,進行呼叫。
步驟如下:
1、你先要把"好友某某"記錄在通訊錄中。
2、撥打電話的時候通過通訊錄中找到"好友某某",並撥通回電話。
3、當好友某某電話號碼更新的時候,需要通知到你,並修改通訊錄服務中的號碼。
從這個過程中我們看到了一些特點:
1、把 "好友某某" 的電話號碼寫入通訊錄中,統一在通訊錄中維護,後續號碼變更也是更新到通訊錄中, 這個過程就是服務註冊的過程。
2、後續我們通過"好友某某"就可以定位到通訊錄中的電話號碼,並撥通電話, 這個過程理解為服務發現的過程。
而我們 微服務架構中的服務註冊與發現結構如下圖所示 :
圖片中是一個典型的微服務架構,這個結構中主要 涉及到三大角色:
provider - 服務提供者
consumer - 服務消費者
register center - 註冊中心
它們之間的 關係大致如下:
1、每個微服務在啟動時,將自己的網路地址等資訊(微服務的ServiceName、IP、Port、MetaData等)註冊到註冊中心,註冊中心儲存這些資料。
2、服務消費者從註冊中心查詢服務提供者的地址,並通過該地址呼叫服務提供者的介面。
3、各個微服務與註冊中心使用一定機制(例如心跳)通訊。如果註冊中心與某微服務長時間無法通訊,就會登出該例項。
優點如下:
1、解耦: 服務消費者跟服務提供者解耦,各自變化,不互相影響
2、擴充套件: 服務消費者和服務提供者增加和刪除新的服務,對於雙方沒有任何影響
3、中介者設計模式:用一箇中介物件來封裝一系列的物件互動, 這是一種多對多關係的中介者模式。
從功能上拆開主要有三塊:服務註冊、服務發現,和註冊中心。我們一個一個來看。
1.1 服務註冊
如圖中,為Register註冊中心註冊一個服務資訊,會將服務的資訊:ServiceName、IP、Port以及服務例項MetaData元資料資訊寫入到註冊中心。當服務發生變化的時候,也可以更新到註冊中心。
服務提供者(服務例項) 的服務註冊模型是一種簡單、容易理解、流行的服務註冊模型,其在多種技術生態中都有所體現:
1、在K8S生態中,通過 K8S Service服務資訊,和Pod的 endpoint(用來記錄service對應的pod的訪問地址)來進行註冊。
2、在Spring Cloud生態中,應用名 對應 服務Service,例項 IP + Port 對應 Instance例項。比較典型的就是A服務,後面對應有多個例項做負載均衡。
3、在其他的註冊元件中,比如 Eureka、Consul,服務模型也都是 服務→ 服務例項。
可以認為服務例項是一個真正的實體的載體,服務是對這些相同能力或者相同功能服務例項的一個抽象。
1.2 服務發現
服務發現實際就是我們查詢已經註冊好的服務提供者,比如 p->p.queryService(serviceName),通過服務名稱查詢某個服務是否存在,如果存在,
返回它的所有例項資訊,即一組包含ip 、 port 、metadata元資料資訊的endpoints資訊。
這一組endpoints資訊一般會被快取在本地,如果註冊中心掛掉,可保證段時間內依舊可用,這是去中心化的做法。對於單個 Service 後面有多個 Instance的情況(如上圖),做 load balance。
服務發現的方式一般有兩種:
1、拉取的方式:服務消費方(Consumer)主動向註冊中心發起服務查詢的請求。
2、推送的方式:服務訂閱/通知變更(下發):服務消費方(Consumer)主動向註冊中心訂閱某個服務,當註冊中心中該服務資訊發生變更時,註冊中心主動通知消費者。
1.3 註冊中心
註冊中心提供的基本能力包括:提供服務註冊、服務發現 以及 健康檢查。
服務註冊跟服務發現上面已經詳細介紹了, 健康檢查指的是指註冊中心能夠感知到微服務例項的健康狀況,便於上游微服務例項及時發現下游微服務例項的健康狀況。採取必備的訪問措施,如避免訪問不健康的例項。
主要的檢查方式包括:
1、服務Provider 進行 TTL 健康彙報(Time To Live,微服務Provider定期向註冊中心彙報健康狀態)。
2、註冊中心主動檢查服務Provider介面。
綜合我們前面的內容,可以總結下注冊中心有如下幾種能力:
1、高可用
這個主要體現在兩個方面。一個方面是,註冊中心本身作為基礎設施層,具備高可用;第二種是就是前面我們說到的去中心化,極端情況下的故障,短時間內是不影響微服務應用的呼叫的
2、視覺化操作
常用的註冊中心,類似 Eureka、Consul 都有比較豐富的管理介面,對配置、服務註冊、服務發現進行視覺化管理。
3、高效運維
註冊中心的文件豐富,對運維的支援比較好,並且對於服務的註冊是動態感知獲取的,方便動態擴容。
4、許可權控制
資料是具有敏感性,無論是服務資訊註冊或服務是呼叫,需要具備許可權控制能力,避免侵入或越權請求
5、服務註冊推、拉能力
這個前面說過了,微服務應用程式(服務的Consumer),能夠快速感知到服務例項的變化情況,使用拉取或者註冊中心下發的方式進行處理。
2 現下的主流注冊中心
2.1 Eureka
2.1.1 介紹
Eureka是Netflix OSS套件中關於服務註冊和發現的解決方案。因為Spring Cloud 在它的微服務解決方案中對Eureka進行了整合,並作為優先推薦方案進行宣傳,所以早期有用 Spring Cloud 來建設微服務系統的同學會比較熟悉。
目前大量公司的微服務系統中依舊使用Eureka作為註冊中心,它的核心設計思想也被後續大量註冊中心產品借鑑。但目前 Eureka 2.0已經停止維護 ,所以新的微服務架構設計中,不再建議使用。
Spring Cloud Netflix主要分為兩個部分:
1、Eureka Server: 作為註冊中心Server端,向微服務應用程式提供服務註冊、發現、健康檢查等能力。
2、Eureka Client: 微服務應用程式Client端,用以和Eureka Server進行通訊。
Eureka有比較友好的管理介面,如上圖所示:
1、System Status:顯示當前Eureka Server資訊。
2、Instances Current registered with Eureka:在Eureka Server當前註冊的資料,在Spring Cloud生態中,被註冊的服務可以唄發現並羅列在這個地方。
3、General Info:基本資訊,如cpu、記憶體、環境等。
2.1.2 整體架構
Eureka Server可以執行多個例項來構建叢集,解決單點問題,但不同於ZooKeeper的選舉leader的過程,Eureka Server採用的是Peer to Peer對等通訊。
所以他有如下特點:
1、 去中心化的架構:無master/slave區分,每一個Peer都是對等的。 在這種架構中,節點通過彼此互相註冊來提高可用性,每個節點需要新增一個或多個有效的serviceUrl指向其他節點。每個節點都可被視為其他節點的副本。
2、 故障轉移/故障恢復 :如果某臺Eureka Server宕機,Eureka Client的請求會自動切換到新的Eureka Server節點,當宕機的伺服器重新恢復後,Eureka會再次將其納入到伺服器叢集管理之中。
3、節點複製:當節點開始接受客戶端請求時,所有的操作都會進行replicateToPeer(節點間複製)操作,將請求複製到其他Eureka Server當前所知的所有節點中。
同理,一個新的Eureka Server節點啟動後,會首先嚐試從鄰近節點獲取所有例項登錄檔資訊,完成初始化。
4、CAP模式:複製演算法非強一致性演算法,而是當有資料寫入時,Eureka Server將資料同步給其他的節點, 因此Eureka在CAP提系統(一致性、可用性、分割槽容錯性)是典型的AP系統。
2.1.3 接入Spring Cloud
如上圖所示:
1、 Provider 服務提供者: 服務向註冊中心註冊服務資訊,即 服務 -> 服務例項 資料模型, 同時定時向註冊中心彙報健康檢查,如果一定時間內(一般90s)沒有進行心跳彙報,則會被註冊中心剔除。
所以這邊注意,註冊中心感知到應用下線並進行剔除這個過程可能比較長。
2、 Consumer 服務消費者 :服務向註冊中心獲取所需服務對應的服務例項資訊。這邊需要注意,Eureka不支援訂閱,因此在Spring Cloud生態中,通過定時拉取方式從註冊中心中獲取所需的服務例項資訊。
3、 Remote Call 遠端呼叫: Consumer從註冊中心獲取的Provider的例項資訊,通過 Load Balance的策略,確定一個實際的例項,發起遠端呼叫。
2.2 ZooKeeper
2.2.1 介紹
作為一個分散式的、開源的協調服務,ZooKeeper實現了一系列基礎功能,包括簡單易用的介面。
這些介面被用來實現服務的註冊與發現功能。並實現一些高階功能,如資料同步、分散式鎖、配置中心、叢集選舉、命名服務等。
在資料模型上,類似於傳統的檔案系統,節點型別分為:
1、持久節點:節點建立後,就一直存在,除非執行刪除操作,主動刪掉這個節點。
2、臨時節點(註冊中心場景下的主要實現機制):臨時節點的生命週期和客戶端會話繫結。也就是說,如果客戶端會話失效,那麼這個節點就會自動被清除掉。
在實際場景下,微服務啟動的時候,會建立一個服務臨時節點,等把服務停止,短時間後節點就沒有了。
Zookeeper有如下特點:
1、最終一致性 :為客戶端展示同一檢視,這是zookeeper最重要的功能。
2、可靠性 :如果訊息被到一臺伺服器接受,那麼它將被所有的伺服器接受。
3、實時性 :Zookeeper不能保證兩個客戶端能同時得到剛更新的資料,如果需要最新資料,應該在讀資料之前呼叫sync()介面。
4、等待無關(wait-free) :慢的或者失效的client不干預快速的client的請求。
5、原子性 :更新只能成功或者失敗,沒有中間狀態。
6、順序性 :所有Server,同一訊息釋出順序一致。
2.2.2 整體架構
上圖是Zookeeper 的服務架構,他有如下流程:
1、 多個節點組成分散式架構,每個Server在記憶體中儲存一份資料;
2、通過選舉產生leader, 通過 Paxos(帕克索斯)強一致性演算法 進行保證,是典型的CP結構。
3、 Leader負責處理資料更新 等操作(Zab協議);
2.2.3 接入Dubbo生態
上圖中的角色如下:
Provider:提供者,服務釋出方
Consumer:消費者, 呼叫服務方
Container:Dubbo容器.依賴於Spring容器
Registry:註冊中心,當Container啟動時把所有可以提供的服務列表上Registry中進行註冊,告訴Consumer提供了什麼服務,以及服務方的位置
Monitor:監聽器
說明:ZooKeeper在註冊中心方面對Dubbo生態支援的比較好。服務提供者Providerzai Container啟動時主動向註冊中心Registry ZooKeeper中註冊資訊。
服務消費者Consumer啟動時向註冊中心Registry ZooKeeper中訂閱註冊中心,當Provider的資訊發生變化時,註冊中心ZooKeeper會主動向Consumer進行推送通知變更。
這邊注意與Eureka的區別,這是主動推送通知,是註冊中心下發的操作。
2.3 Consul
2.3.1 介紹
Consul是HashiCorp推出的一款軟體,是一個Service Mesh解決方案,提供了功能豐富的控制面功能:
1、Service Discovery(服務發現)
2、Configuration(配置化)
3、Segmentation Functionality
這些功能可以根據需要獨立使用,或者將它們一起使用用來構建完整的Service Mesh。
Consul提供的關鍵功能如下:
1、Service Discovery:服務註冊/發現功能。
2、Health Checking:健康檢查,豐富的健康檢查方式;
3、KV Store:KV儲存功能,可應用多種場景,如動態配置儲存,分散式協調、leader選舉等。
4、Multi DataCenter:多資料中心。
2.3.2 整體架構
如上圖為Consul的架構,這邊對技術點做一下說明:
1、Raft: 一種分散式一致性演算法,Consul使用該演算法報紙強一致性,所以也是典型的CP模式
2、Client:Client是一種agent,其將會重定向所有的RPC 請求到Server。Client是無狀態的,其主要參與LAN Gossip協議池。其佔用很少的資源,並且消耗很少的網路頻寬。
3、Server:Server是一種agent,其包含了一系列的責任包括:參與Raft協議寫半數(Raft Quorum)、維護叢集狀態、響應RPC響應、和其他Datacenter通過WAN gossip交換資訊和重定向查詢請求至leader或者遠端Datacenter。
4、Datacenter: Datacenter其是私有的、低延遲、高頻寬的網路環境,去除了在公共網路上的網路互動。
5、Consensus: Consensus一致性在leader 選舉、順序執行transaction 上。當這些事務已經提交至有限狀態機(finite-state machine)中,Consul定義consensus作為複製狀態機的一致性。本質上使用實現了Raft協議,對於具體實現細節可參考 Consensus Protocol。
6、Gossip:Consul使用了Serf,其提供了Gossip協議多種用途,Serf提供成員關係、失敗檢查和事件廣播。
7、LAN Gossip: Local Area Network Gossip其包含在同一個網路環境或Datacenter的節點。
8、WAN Gossip: Wide Area Network Gossip 其只包含Server節點,這些server分佈在不同的datacenter中,其主要通過因特網或廣域網相互交流。
9、RPC: 遠端過程呼叫,用於服務之間的通訊。
10、CAP抉擇:在高可用方面,Consul使用Raft協議作為其分散式一致性協議,本身對故障節點有一定的容忍性,在單個DataCenter中Consul叢集中節點的數量控制在2*n + 1個節點,其中n為可容忍的宕機個數,通常為3個節點。
所以是典型的CP模式。
根據Consul 的選舉機制和服務原理,我們有兩個注意點 :
1、部署Consul Service 節點應該奇數為宜,因為+1的偶數節點和奇數節點可容忍的故障數是一樣的,比如上圖3和4,另一方面,偶數個節點在選主節點的時候可能會出現二分選票的情況,還得重新選舉。
2、Consul Service 節點數不是越多越好,雖然Server數量越多可容忍的故障數越多,但是Raft進行日誌複製也是很耗時間的,而且Server數量越多,效能越低,所以結合實際場景,一般建議Server部署3個即可。
有興趣的同學可以去Consul官網看看它的選舉機制,還可以對比下Redis中Sentinel模式。
2.3.3 生態對接
對接Spring Cloud生態
Consul作為註冊中心,整合在Spring Cloud生態。可以看出,跟Eureka對接到Spring Cloud 生態的過程很像。
但是這邊的健康檢查更豐富,可以有多種不同的的Check方式:
- Script check(Script+ Interval)
- 基於HTTP請求
- 基於tcp請求
- 基於grpc請求
2.4 總結對比
指標 | Eureka | Zookeeper | Consul | Etcd |
一致性協議 | AP | CP(Paxos演算法) | CP(Raft演算法) | CP(Raft演算法) |
健康檢查 | TTL(Time To Live) | TCP Keep Alive | TTL\HTTP\TCP\Script | Lease TTL KeepAlive |
watch/long polling | 不支援 | watch | long polling | watch |
雪崩保護 | 支援 | 不支援 | 不支援 | 不支援 |
安全與許可權 | 不支援 | ACL | ACL | RBAC |
是否支援多資料中心 | 是 | 否 | 是 | 否 |
是否有管理介面 | 是 | 否(可用第三方ZkTools) | 是 | 否 |
Spring Cloud 整合 | 支援 | 支援 | 支援 | 支援 |
Dubbo 整合 | 不支援 | 支援 | 支援 | 不支援 |
K8S 整合 | 不支援 | 不支援 | 支援 | 支援 |
這邊是對業內4種註冊中心各緯度上的對比,Eureka是典型的AP型別,Zookeeper和Consul是典型的CP型別。 如何選擇取決你的業務是傾向A:高可用性 還是 C:強一致性。
當然,業務是複雜的,在真正的技術選型時,還是要根據自己的實際業務現狀來判斷。有一些傾向,比如你的系統是Spring Cloud體系下,那優先選擇Eureka、Consul。
如果業務會更多向雲原生對齊,則Consul、Etcd會是比較優先的選擇。
- 面試官:cglib為什麼不能代理private方法?
- 想看Dubbo原始碼?一定要先看一看這一篇!
- 死磕synchronized二:系統剖析延遲偏向篇一
- 架構與思維:高併發下解決主從延時的一些思路
- 道與術
- OopMap看不懂,怎麼調優哇
- Kafka 精妙的高效能設計(下篇)
- 一次tcp視窗被填滿問題的排查實踐
- 搶了個票,還以為發現了12306的系統BUG
- 微服務5:服務註冊與發現(實踐篇)
- 看一遍就理解:零拷貝詳解
- 分散式:分散式系統下的唯一序列
- 面試官:為什麼jdk動態代理只能代理介面實現類?
- 揭開記憶體屏障的神祕面紗
- 微服務4:服務註冊與發現
- 我就奇了怪了,STW到底是怎麼做到的
- 這樣使用 IDEA ,效率提升10倍!| IDEA 高效使用指南
- 從hotspot原始碼層面剖析Java的多型實現原理
- 垃圾回收全集之十二:GC 調優的實戰篇—Weak, Soft 及 Phantom 引用
- JVM的多型是如何實現的