今天在一個朋友的羣裏聊起 RPC 這類框架,剛好我也在寫 RSF(一個分佈式RPC框架)對於分佈式環境來講,一個服務會有多個副本,調用端在多個副本之間如何抉擇是一個很明顯的問題。因而註冊中心應運而生。 緩存
但是我心中一直有一個疙瘩,總以爲註冊中心這個東西大可沒必要要的。因而索性設計一個套去中心化的解決方案,用以去中心化的分佈式 RPC 框架的設計。 服務器
先說一下中心化的分佈式 RPC 工做方式, 通常狀況下「註冊中心」負責接受服務上線時的心跳請求,而且「註冊中心」會維持一個活躍的服務列表。當有消費者上線時「註冊中心」會告訴消費者可用的服務列表。而後消費者會本身去輪詢調用不一樣服務地址已完成調用。 網絡
若是某一個服務節點當掉了「註冊中心」就檢測不到節點的心跳因而會通知消費端服務下線。其實「註冊中心」要作的一件事情就是監控死掉的服務。要想知道死掉的服務有兩種辦法:一種心跳監聽、另外一種主動發現。 架構
「註冊中心」走的是心跳監聽的路線。若是遇到剛死的服務「註冊中心」還沒來得及通知,那調用發起的確定還要在作一次異常重試。因而在客戶端又多了一個主動發現的容錯方案。 框架
我以爲這是徹底重複的工做是不必的,二者留一個就能夠了。何況客戶端去調用遠程服務時候,既然都要去發現服務是否真的死掉,爲嘛還要搞一個「註冊中心」? 分佈式
並且「註冊中心」一旦掛掉,新上線的機器沒法及時更新到 IP 列表,這樣的影響會更大。爲了不這種事情,咱們又把「註冊中心」作了熱備。 這種設計是否是過重了呢? 優化
因此我以爲必定要去中心化! spa
BT 軟件下載,有一個很好的思想。 設計
BT在下載軟件你只要知道一個種子地址,剩下的客戶端會根據種子地址去發現更多的可用源來下載文件。咱們可使用這種思想讓服務端在啓動時經過一個源自動發現更多的服務可用地址。 資源
可是這裏有一個問題,咱們先回歸生產環境。一個龐大的集羣可能會有幾十萬個服務在跑,這個已是很大規模了。你不能要求這幾十萬的服務之間相互P2P的調用通訊,這不科學。
因而我想到,只保留 BT 思想裏種子的概念,而後用爬蟲的機制讓機器與機器之間相互分享本身的地址列表和服務列表。這樣一來臺機器只須要知道我想要什麼,而後到本地地址池裏去找本身的資源就能夠了。
本地地址池的創建能夠首先經過種子服務器預熱,只要獲取到一個可用的IP地址列表在本地緩存起來。第二次啓動時就徹底不須要源了。
這個就是自動發現的原理。剩下的就是你只須要一臺種子服務器,負責提供初始的 IP 地址列表就好了。一旦完成第一次啓動RPC客戶端從源中取到了更多可用的源,那麼就再也不須要這個最初的源服務器了。從而也就完成去中心化。
至於死去的服務, 每臺客戶端在遇到調用長時間無響應時候會自動去作降權處理。當超過必定次數以後自動將這個死掉的IP地址處理掉。
有朋友會問,你的種子服務器一旦掛掉怎麼辦?
要知道在這種去中心化的架構裏,種子服務器不是中心。任何一臺服務器都是種子服務器。你只須要讓最早啓動的兩臺服務器之間知道彼此的存在,後面啓動的服務器都會紛紛加入到這個網絡中,分享彼此的地址本。這樣一來每臺服務器都是「中心」了。
當選定的種子服務器當掉了怎麼辦?
每臺服務器在啓動的時候,都會在本地創建一個緩存的地址本。裏面會有不少備選服務地址能夠去鏈接,這些地址都是種子服務器,因此只要你服務成功跑起來一次那麼就什麼都不怕了。
服務掛掉當請求超時對服務地址作降權處理。長期再也不活躍的服務 IP 會被剔除。這樣一來就清爽不少了。
另一個問題也會涉及到註冊中心,那就是「服務治理」,所謂服務治理是指一大堆策略性的配置,比方說流量管控、服務降級、服務熱下線、服務監控以及多機房路由優化。
而我以爲這些東西最總落實在註冊中心上的只能是一些策略性的配置,真正執行策略的仍是分散各個節點上的服務器。所以註冊中心在其中的做用也僅僅是統一策略管理和策略的分發。
若是去中心化的這些策略分發,能夠利用服務器之間分享的方式來傳播變動。這樣一來你只要把策略下發到其中一臺服務的機器上,它便會爲你傳播到全部機器上,服務治理的問題也就解決了。