SOFAStack
S calable O pen F inancial A rchitecture Stack 是螞蟻金服自主研發的金融級分佈式架構,包含了構建金融級雲原生架構所需的各個組件,是在金融場景裏錘鍊出來的最佳實踐。
SOFARegistry 是螞蟻金服開源的具備承載海量服務註冊和訂閱能力的、高可用的服務註冊中心,最先源自於淘寶的第一版 ConfigServer,在支付寶/螞蟻金服的業務發展驅動下,近十年間已經演進至第五代。
GitHub 地址: github.com/alipay/sofa…
3 月 31 日,螞蟻金服正式開源了內部演進了近 10 年的註冊中心產品-SOFARegistry。先前的文章介紹了 SOFARegistry 的演進之路,而本文主要對 SOFARegistry 總體架構設計進行剖析,並着重介紹一些關鍵的設計特色,指望能幫助讀者對 SOFARegistry 有更直接的認識。php
若有興趣,也歡迎加入《剖析 | SOFARegistry 實現原理》系列的共建,認領列表見文末。node
不可免俗地,先介紹一下服務註冊中心的概念。對此概念已經瞭解的讀者,可選擇跳過本節。git
如上圖,服務註冊中心最多見的應用場景是用於 RPC 調用的服務尋址,在 RPC 遠程過程調用中,存在 2 個角色,一個服務發佈者(Publisher)、另外一個是服務訂閱者(Subscriber)。Publisher 須要把服務註冊到服務註冊中心(Registry),發佈的內容一般是該 Publisher 的 IP 地址、端口、調用方式 (協議、序列化方式)等。而 Subscriber 在第一次調用服務時,會經過 Registry 找到相應的服務的 IP 地址列表,經過負載均衡算法從 IP 列表中取一個服務提供者的服務器調用服務。同時 Subscriber 會將 Publisher 的服務列表數據緩存到本地,供後續使用。當 Subscriber 後續再調用 Publisher 時,優先使用緩存的地址列表,不須要再去請求Registry。github
如上圖,Subscriber 還須要能感知到 Publisher 的動態變化。好比當有 Publisher 服務下線時, Registry 會將其摘除,隨後 Subscriber 感知到新的服務地址列表後,不會再調用該已下線的 Publisher。同理,當有新的 Publisher 上線時,Subscriber 也會感知到這個新的 Publisher。redis
在理解了常見的服務註冊中心的概念以後,咱們來看看螞蟻金服的 SOFARegistry 長什麼樣子。如上圖,SOFARegistry 包含 4 個角色:算法
1. Clientspring
提供應用接入服務註冊中心的基本 API 能力,應用系統經過依賴客戶端 JAR 包,經過編程方式調用服務註冊中心的服務訂閱和服務發佈能力。docker
2. SessionServer編程
會話服務器,負責接受 Client 的服務發佈和服務訂閱請求,並做爲一箇中間層將寫操做轉發 DataServer 層。SessionServer 這一層可隨業務機器數的規模的增加而擴容。緩存
3. DataServer
數據服務器,負責存儲具體的服務數據,數據按 dataInfoId 進行一致性 Hash 分片存儲,支持多副本備份,保證數據高可用。這一層可隨服務數據量的規模的增加而擴容。
4. MetaServer
元數據服務器,負責維護集羣 SessionServer 和 DataServer 的一致列表,做爲 SOFARegistry 集羣內部的地址發現服務,在 SessionServer 或 DataServer 節點變動時能夠通知到整個集羣。
(圖片改編自 luyiisme.github.io/2017/04/22/… )
首先放一張常見的服務註冊中心的特性對比,能夠看出,在這些 Feature 方面,SOFARegistry 並不佔任何優點。那麼,咱們爲何還開源這樣的一個系統?SOFARegistry 開源的優點是什麼?下面將着重介紹 SOFARegistry 的特色。
大部分的服務註冊中心繫統,每臺服務器都是存儲着全量的服務註冊數據,服務器之間依靠一致性協議(如 Paxos/Raft/2PC 等)實現數據的複製,或者只保證最終一致性的異步數據複製。「每臺服務器都存儲着全量的服務註冊數據」,在通常規模下是沒問題的。可是在螞蟻金服龐大的業務規模下,服務註冊的數據總量早就超過了單臺服務器的容量瓶頸。
SOFARegistry 基於一致性 Hash 作了數據分片,每臺 DataServer 只存儲一部分的分片數據,隨數據規模的增加,只要擴容 DataServer 服務器便可。這是相對服務發現領域的其餘競品來講最大的特色,詳細介紹見後面《如何支持海量數據》一節。
SOFARegistry 集羣內部使用分層的架構,分別爲鏈接會話層(SessionServer)和數據存儲層(DataServer)。SessionServer 功能很純粹,只負責跟 Client 打交道,SessionServer 之間沒有任何通訊或數據複製,因此隨着業務規模(即 Client 數量)的增加,SessionServer 能夠很輕量地擴容,不會對集羣形成額外負擔。
相比之下,其餘大多數的服務發現組件,如 eureka,每臺服務器都存儲着全量的數據,依靠 eurekaServer 之間的數據複製來傳播到整個集羣,因此每擴容 1 臺 eurekaServer,集羣內部相互複製的數據量就會增多一份。再如 Zookeeper 和 Etcd 等強一致性的系統,它們的複製協議(Zab/Raft)要求全部寫操做被複制到大多數服務器後才能返回成功,那麼增長服務器還會影響寫操做的效率。
對於服務的上下線變化,SOFARegistry 使用推送機制,快速地實現端到端的傳達。詳細介紹見後面《秒級服務上下線通知》一節。
接下來,我將圍繞這些特色,講解 SOFARegistry 的關鍵架構設計原理。
各個角色都有 failover 機制:
注意:這裏只列出核心的模型和字段,實際的代碼中不止這些字段,但對於讀者來講,只要理解上述模型便可。
關於「zone」和「scope」的概念理解,這裏再舉個例子。以下圖所示,物理機房內有 ZoneA 和 ZoneB 兩個單元,PublisherA 處於 ZoneA 裏,因此發佈服務時指定了 zone=ZoneA,PublisherB 處於 ZoneB 裏,因此發佈服務時指定了 zone=ZoneB;此時 Subscriber 訂閱時指定了 scope=datacenter 級別,所以它能夠獲取到 PublisherA 和 PublisherB (若是 Subscriber 訂閱時指定了 scope=zone 級別,那麼它只能獲取到 PublisherA)。
服務註冊和訂閱的示例代碼以下 (詳細可參看官網的《客戶端使用》文檔):
// 構造發佈者註冊表,主要是指定dataInfoId和zone
PublisherRegistration registration = new PublisherRegistration("com.alipay.test.demo.service");
registration.setZone("ZoneA");
// 發佈服務數據,dataList內容是 "10.10.1.1:12200?xx=yy",即只有一個服務數據
registryClient.register(registration, "10.10.1.1:12200?xx=yy");複製代碼
發佈服務數據的代碼示例
// 構造訂閱者,主要是指定dataInfoId,並實現回調接口
SubscriberRegistration registration = new SubscriberRegistration("com.alipay.test.demo.service",
(dataId, userData) -> System.out
.println("receive data success, dataId: " + dataId + ", data: " + userData));
// 設置訂閱維度,ScopeEnum 共有三種級別 zone, dataCenter, global
registration.setScopeEnum(ScopeEnum.dataCenter);
// 將註冊表註冊進客戶端並訂閱數據,訂閱到的數據會以回調的方式通知
registryClient.register(registration);複製代碼
訂閱服務數據的代碼示例
SOFARegistry 服務端在接收到「服務發佈(PublisherRegister)」和「服務訂閱(SubscriberRegister)」以後,在內部會彙總成這樣的一個邏輯視圖。
注意,這個樹形圖只是邏輯上存在,實際物理上 publisherList 和 subscriberList 並非在同一臺服務器上,publisherList 是存儲在 DataServer 裏,subscriberList 是存儲在 SessionServer 裏。
能夠看出來,SOFARegistry 的模型是很是簡單的,大部分服務註冊中心產品的模型也就這麼簡單。好比 eureka 的核心模型是應用(Application)和實例(InstanceInfo),以下圖,1 個 Application 能夠包含多個 InstanceInfo。eureka 和 SOFARegistry 在模型上的主要區別是,eureka 在語義上是以應用(Application)粒度來定義服務的,而SOFARegistry 則是以 dataInfoId 爲粒度,因爲 dataInfoId 實際上沒有強語義,粗粒度的話能夠做爲應用來使用,細粒度的話則能夠做爲 service 來使用。基於以上區別,SOFARegistry 能支持以接口爲粒度的 SOFARPC 和 Dubbo,也支持以應用爲粒度的 SpringCloud,而 eureka 因爲主要面向應用粒度,所以最多的場景是在springCloud 中使用,而 Dubbo 和 SOFAPRC 目前均未支持 eureka。
另外,eureka 不支持 watch 機制(只能按期 fetch),所以不須要像 SOFARegistry 這樣的 Subscriber 模型。
(圖片摘自 www.jianshu.com/p/0356b7e9b…)
最後再展現一下 SOFARPC 基於 Zookeeper 做爲服務註冊中心時,在 Zookeeper 中的數據結構(以下圖),Provider/Consumer 和 SOFARegistry 的 Publisher/Subscriber 相似,最大的區別是 SOFARegistry 在訂閱的維度上支持 scope(zone/datacenter),即訂閱範圍。
從前面的架構介紹中咱們知道,SOFARegistry 存在數據服務器(DataServer)和會話服務器(SessionServer)這 2 個角色。爲了突破單機容量瓶頸,DataServer 基於一致性 Hash 存儲着不一樣的數據分片,從而能支持螞蟻金服海量的服務數據,這是易於理解的。但 SessionServer 存在的意義是什麼?咱們先來看看,若是沒有SessionServer的話,SOFARegistry 的架構長什麼樣子:
如上圖,全部 Client 在註冊和訂閱數據時,根據 dataInfoId 作一致性 Hash,計算出應該訪問哪一臺 DataServer,而後與該 DataServer 創建長鏈接。因爲每一個 Client 一般都會註冊和訂閱比較多的 dataInfoId 數據,所以咱們能夠預見每一個 Client 均會與好幾臺 DataServer 創建鏈接。這個架構存在的問題是:「每臺 DataServer 承載的鏈接數會隨 Client 數量的增加而增加,每臺 Client 極端的狀況下須要與每臺 DataServer 都建連,所以經過 DataServer 的擴容並不能線性的分攤 Client 鏈接數」。
講到這裏讀者們可能會想到,基於數據分片存儲的系統有不少,好比 Memcached、Dynamo、Cassandra、Tair 等,這些系統都也是相似上述的架構,它們是怎麼考慮鏈接數問題的?其實業界也給出了答案,好比 twemproxy,twitter 開發的一個 memcached/redis 的分片代理,目的是將分片邏輯放到 twemproxy 這一層,全部 Client 都直接和 twemproxy 鏈接,而 twemproxy 負責對接全部的 memcached/Redis,從而減小 Client 直接對memcached/redis 的鏈接數。twemproxy 官網也強調了這一點:「It was built primarily to reduce the number of connections to the caching servers on the backend」,以下圖,展現的是基於 twemproxy 的 redis 集羣部署架構。相似 twemproxy 的還有 codis,關於 twemproxy 和 codis 的區別,主要是分片機制不同,下節會再談及。
(圖片摘自 www.hanzhicaoa.com/1.php?s=twe…)
固然也有一些分佈式 KV 存儲系統,沒有任何鏈接代理層。好比 Tair (Alibaba 開源的分佈式 KV 存儲系統),只有 Client、DataServer、ConfigServer 這 3 個角色,Client 直接根據數據分片鏈接多臺 DataServer。但螞蟻金服內部在使用 Tair 時自己會按業務功能垂直劃分出不一樣的 Tair 集羣,所部署的機器配置也比較高,並且 Tair 的 Client 與 data server 的長鏈接一般在空閒一段時間後會關閉,這些都有助於緩解鏈接數的問題。固然,即使如此,Tair 的運維團隊也在時刻監控着鏈接數的總量。
通過上面的分析,咱們明白了爲數據分片層(DataServer)專門設計一個鏈接代理層的重要性,因此 SOFARegistry 就有了 SessionServer 這一層。如圖,隨着 Client 數量的增加,能夠經過擴容 SessionServer 就解決了單機的鏈接數瓶頸問題。
面對海量數據,想突破單機的存儲瓶頸,惟一的辦法是將數據分片,接下來將介紹常見的有 2 種數據分片方式。
傳統的一致性 Hash 算法,每臺服務器被虛擬成 N 個節點,以下圖所示(簡單起見虛擬份數 N 設爲 2 )。每一個數據根據 Hash 算法計算出一個值,落到環上後順時針命中的第一個虛擬節點,即負責存儲該數據。業界使用一致性 Hash 的表明項目有 Memcached、Twemproxy 等。
一致性 Hash 分片的優勢:在虛擬節點足夠多的狀況下,數據分片在每臺節點上是很是分散均勻的,而且增長或減小節點的數量,仍是能維持數據的平衡。好比當 Memcached 單機遇到內存瓶頸時,經過擴容 Memcached 機器,數據將會被從新均勻地分攤到新的節點上,所以每臺 Memcached 服務器的內存就能獲得下降。當某臺服務器宕機時,數據會被從新均勻地分攤到剩餘的節點上,以下圖所示,A 機器宕機,原先在 A 機器上的數據會分別從新分攤到 B 機器和 C 機器。
一致性 Hash 分片的缺點:分片範圍不固定(一旦節點數發生變化,就會致使分片範圍變化)。嚴格來講,這不是一致性 Hash 的缺點,而是它的特色,這個特色在追求數據分散的場景下是優勢,但在談及數據複製的這個場景下它是個缺點。從上面的機器宕機過程,能夠看到,僅擴縮容少許節點,就會影響到其餘大部分已有節點的分片範圍,即每臺節點的分片範圍會由於節點數變化而發生變化。以下圖,當 A 宕機時,分片 6 和 1 合併成 7,分片 3 和 4 合併成 8,就是說,A 宕機後,B 和 C 的分片範圍都發生了變化。
「分片範圍不固定」,帶來的問題是:難以實現節點之間數據多副本複製。這個結論可能不太好理解,我舉個例子:若是要實現節點之間數據可以複製,首先每一個節點須要對數據分片保留操做日誌,節點之間依靠這些操做日誌進行增量的日誌同步。好比上圖的左半邊,B 節點負責分片 1 和 5,所以 B 節點須要使用 2 個日誌文件(假設叫作 data-1.log 和 data-5.log)記錄這 2 個分片的全部更新操做。當 A 宕機時(上圖的右半邊),B 節點負責的分片變成 7 和 5,那麼 data-1.log 日誌文件就失效了,由於分片 1 不復存在。可見,在分片範圍易變的狀況下,保存數據分片的操做日誌,並無意義。這就是爲何這種狀況下節點之間的日誌複製很差實現的緣由。
值得一提的是,Twemproxy 也是由於「分片範圍不固定(一旦節點數發生變化,就會致使分片範圍變化)」這個問題,因此不支持平滑的節點動態變化。好比使用 Twemproxy + Redis,若是要擴容 Redis 節點,那麼須要用戶本身實現數據遷移的過程,這也是後來 Codis 出現的緣由。固然,對於不須要數據多副本複製的系統,好比 Memcached,因爲它的定位是緩存,不保證數據的高可靠,節點之間不須要作數據多副本複製,因此不存在這個顧慮。
思考:對於那些須要基於數據多副本複製,來保證數據高可靠的 kv 存儲系統,好比 Tair、dynamo 和 Cassandra,它們是怎麼作數據分片的呢?
預分片機制,理解起來比一致性 Hash 簡單,首先須要從邏輯上將數據範圍劃分紅 N 個大小相等的 slot,而且 slot 數量(即 N 值)後續不可再修改。而後,還須要引進「路由表」的概念,「路由表」負責存放這每一個節點和 N 個slot 的映射關係,並保證儘可能把全部 slot 均勻地分配給每一個節點。在對數據進行路由時,根據數據的 key 計算出哈希值,再將 hash 值對 N 取模,這個餘數就是對應 key 的 slot 位置。好比 Codis 默認將數據範圍分紅 1024 個 slots,對於每一個 key 來講,經過如下公式肯定所屬的 slotId:slotId = crc32(key) % 1024,根據 slotId 再從路由表裏找到對應的節點。預分片機制的具體原理以下圖。
能夠看出來,相對傳統的一致性 Hash 分片,預分片機制的每一個 slot 的大小(表明數據分片範圍)是固定的,所以解決了「分片範圍不固定」的問題,如今,節點之間能夠基於 slot 的維度作數據同步了。至於 slot 之間數據複製的方式,好比「採起異步複製仍是同步複製」,「複製多少個節點成功纔算成功」,不一樣系統的因其 cap 定位不一樣,實現也大有不一樣,這裏沒法展開講。
接下來,咱們看看節點增刪的過程。
以下圖,副本數爲 2,路由表裏每一個 slot id 須要映射到 2 個節點,1 個節點存儲主副本,1 個節點存儲備副本。對於 S1 的全部寫操做,須要路由到 nodeA,而後 nodeA 會將 S1 的操做日誌同步給 nodeB。若是 nodeA 發生宕機,則系統須要修改路由表,將 nodeA 所負責的 slot ( 如圖中的 S1和 S3 ) 從新分配給其餘節點,如圖,通過調整,S1 的節點變爲 nodeB 和 nodeC,S3 的節點變爲 nodeC 和 nodeE。而後系統會命令 nodeC 和 nodeE 開始作數據複製的工做,複製過程不會影響到 S1 和 S3 對外服務,由於 nodeC 和 nodeE 都屬於備副本(讀寫都訪問主副本)。複製完成後方可結束。
節點擴容的過程比節點宕機稍微複雜,由於新節點的加入可能致使 slot 遷移,而遷移的過程當中須要保證系統仍能夠對外服務。如下圖爲例,擴容 nodeF 以後,系統須要對路由表的從新平衡,S1 的主節點由 nodeA 變爲 nodeF,S12 的備節點由 nodeC 變爲 nodeF。咱們講一下 S1 的數據遷移過程:首先客戶端所看到的路由表還不會發生變化,客戶端對 S1 的讀寫請求仍然會路由到 nodeA。與此同時 nodeA 開始將 S1 的數據複製給 nodeF;而後,當 nodeF 即將完成數據的備份時,短暫地對 S1 禁寫,確保 S1 不會再更新,而後 nodeF 完成最終的數據同步;最後,修改路由表,將 S1 的主節點改成 nodeF,並將最新的路由表信息通知給 Client,至此就完成 S1 的遷移過程。Client 後續對 S1 的讀寫都會發送給 nodeF。
通常來講,管理路由表、對 Client 和 全部node 發號施令的功能(能夠理解成是「大腦」),一般由單獨的角色來承擔,好比 Codis 的大腦是 codis-conf + Zookeeper/Etcd,Tair 的大腦是 ConfigServer。下圖是 Tair 官方展現的部署架構圖,ConfigServer 由 2 臺服務器組成,一臺 master,一臺 slave。
Tair(Alibaba 開源的分佈式 KV 存儲系統)架構圖
總結一下,「一致性 Hash 分片機制」 和 「預分片機制」 的主要區別:
在虛擬節點足夠多的狀況下,數據分片在每臺節點上是很是分散均勻的,即便增長或減小節點的數量,仍是能維持數據的平衡,而且不須要額外維護路由表。可是,因爲「分片範圍不固定(一旦節點數發生變化,就會致使分片範圍變化)」的特色,致使它不適用於須要作數據多副本複製的場景。目前業界主要表明項目有 Memcached、Twemproxy 等。
經過事先將數據範圍等分爲 N 個 slot,解決了「分片範圍不固定」的問題,所以能夠方便的實現數據的多副本複製。但須要引進「路由表」,而且在節點變化時可能須要作數據遷移,實現起來也不簡單。目前業界主要表明項目有 Dynamo、Casandra、Tair、Codis、Redis cluster 等。
SOFARegistry 的 DataServer 須要存儲多個副本的服務數據,其實比較適合選擇「預分片機制」,但因爲歷史緣由,咱們的分片方式選擇了「一致性 Hash分片」。在「一致性 Hash分片」的基礎上,固然也不意外地遇到了 「分片數據不固定」這個問題,致使 DataServer 之間的數據多副本複製實現難度很大。最後,咱們選擇在 DataServer 內存裏以 dataInfoId 的粒度記錄操做日誌,而且在 DataServer 之間也是以 dataInfoId 的粒度去作數據同步。聰明的讀者應該看出來了,其實思想上相似把每一個 dataInfoId 當作一個 slot 去對待。這個作法很妥協,好在,服務註冊中心的場景下,dataInfoId 的總量是有限的(以螞蟻的規模,每臺 DataServer 承載的 dataInfoId 數量也就在數萬的級別),所以也勉強實現了 dataInfoId 維度的數據多副本。
如上圖,A-F 表明 6 個 dataInfoId 數據。使用一致性 Hash 分片後,DataServer1 負責 A 和 D,DataServer2 負責 B 和 E,DataServer3 負責 C 和 F。而且每一個數據均有 3 個副本。對 A 的寫操做是在 DataServer1 即主副本上進行,隨後 DataServer1 將寫操做異步地複製給 DataServer2 和 DataServer3,DataServer2 和 DataServer3 將寫操做應用到內存中的 A 備副本,這樣就完成了多副本間的數據複製工做。
首先,咱們簡單看一下業界其餘註冊中心的健康檢測機制:
SOFARegistry 的健康檢測
咱們能夠看到上述其餘註冊中心的健康檢測都有個共同的關鍵詞:「按期」,按期檢測的時間週期一般設置爲秒級,好比 3 秒、5 秒或 10 秒,甚至更長,也就是說服務的健康狀態老是滯後的。螞蟻金服的註冊中心從最初的版本設計開始,就把健康狀態的及時感知,當作一個重要的設計目標,特別是須要作到「服務宕機能被及時發現」。爲此, SOFARegistry 在健康檢測的設計上作了這個決定:「服務數據與服務發佈者的實體鏈接綁定在一塊兒,斷連立刻清數據」,我簡稱這個特色叫作鏈接敏感性。
鏈接敏感性:在 SOFARegistry 裏,全部 Client 都與 SessionServer 保持長鏈接,每條長鏈接都會有基於 bolt 的鏈接心跳,若是鏈接斷開,Client 會立刻從新建連,時刻保證 Client 與 SessionServer 之間有可靠的鏈接。
SOFARegistry 將服務數據 (PublisherRegister) 和服務發佈者 (Publisher) 的鏈接的生命週期綁定在一塊兒:每一個 PublisherRegister 有一個屬性是 connId,connId 由註冊本次服務的 Publisher 的鏈接標識 (IP 和 Port)構成, 意味着,只要該 Publisher 和 SessionServer 斷連,數據就失效。Client 從新建連成功後,會從新註冊服務數據,但從新註冊的服務數據會被當成新的數據,由於換了鏈接以後,Publisher 的 connId 不同了。
好比,當服務的進程宕機時,通常狀況下 os 會立刻斷開進程相關的鏈接(即發送 FIN),所以 SessionServer 能立刻感知鏈接斷開事件,而後把該 connId 相關的全部 PublisherRegister 都清除,並及時推送給全部訂閱者 (Subscriber)。固然,若是隻是網絡問題致使鏈接斷開,實際的進程並無宕機,那麼 Client 會立刻重連 SessionServer 並從新註冊全部服務數據。對訂閱者來講它們所看到的,是發佈者經歷短暫的服務下線後,又從新上線。若是這個過程足夠短暫(如 500ms 內發生斷連和重連),訂閱者也能夠感覺不到,這個是 DataServer 內部的數據延遲合併的功能,這裏不展開講,後續在新文章裏再介紹。
須要認可的是,SOFARegistry 太過依賴服務所綁定的鏈接狀態,當網絡不穩定的狀況下,大量服務頻繁上下線,對網絡帶寬會帶來一些不必的浪費,甚至若是是 SessionServer 整個集羣單方面存在網絡問題,那麼可能會形成誤判,這裏也缺少相似 eureka 那樣的保護模式。另外,SOFARegistry 目前不支持自定義的 healthcheck 機制,因此當機器出現假死的狀況(服務不可用,但鏈接未斷且有心跳),是沒法被感知的。
一次服務的上線(註冊)過程
服務的上下線過程,是指服務經過代碼調用作正常的註冊(publisher.register) 和 下線(publisher.unregister),不考慮由於服務宕機等意外狀況致使的下線。如上圖,大概呈現了「一次服務註冊過程」的服務數據在內部流轉過程。下線流程也是相似,這裏忽略不講。
基於對上下線流程的初步認識後,這裏對 SOFARegistry 內部角色之間的數據交互方式作一下歸納:
總結,本節介紹了 SOFARegistry 實現秒級的服務上下線通知的原理,主要是 2 個方面,第一是服務的健康檢測,經過鏈接敏感的特性,對服務宕機作到秒級發現,但爲此也帶來「網絡不穩定致使服務頻繁上下線」的負面影響;第二是內部角色之間的「推」和「拉」的機制,整個服務上下線流程都以實時的「推」爲主,所以才能作到秒級的通知。
本文爲 SOFARegistry 的架構介紹,但願你們對 SOFARegistry 有一個初步的認識和了解。同時,咱們開啓了《剖析 | SOFARegistry 實現原理》系列,會逐步詳細介紹各個部分的代碼設計和實現,預計按照以下的目錄進行:
若是有同窗對以上某個主題特別感興趣的,能夠留言討論,咱們會適當根據你們的反饋調整文章的順序,謝謝你們關注 SOFA ,關注 SOFARegistry,咱們會一直與你們一塊兒成長。
直接回複本公衆號想認領的文章名稱,咱們將會主動聯繫你,確認資質後,便可加入,It's your show time!
除了源碼解析,也歡迎提交 issue 和 PR:
SOFARegistry:github.com/alipay/sofa…
公衆號:金融級分佈式架構(Antfin_SOFA)