萬字長文,助你吃透Eureka服務發現機制!

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"微服系列文章"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第1篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/83386f6d764984f3b64b760fb","title":""},"content":[{"type":"text","text":"“四個維度” 講明白什麼是微服務!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第2篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/e4c9866b723b7c4f9cc272050","title":""},"content":[{"type":"text","text":"微服務涉及的技術生態有哪些?"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第3篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/13a6973621381b27bbcd9ab45","title":""},"content":[{"type":"text","text":" 微服務-爲什麼要有服務發現與註冊?"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第4篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/c6139a5776e139d1b76b2e856","title":""},"content":[{"type":"text","text":" 萬字長文,助你吃透Eureka服務發現機制!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"前言"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在前面幾篇系列文章中,我們對"},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/83386f6d764984f3b64b760fb","title":""},"content":[{"type":"text","text":"微服務的基本概念"}]},{"type":"text","text":"、"},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/e4c9866b723b7c4f9cc272050","title":""},"content":[{"type":"text","text":"微服務的技術生態"}]},{"type":"text","text":"等,做了簡單的闡述。對於分佈式系統或微服務,服務發現是最基礎、最核心、最不可缺的能力。然而許多人對服務發現有一種說不清,道不明,似懂非懂的感覺。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這都無可厚非,畢竟服務發現涉及到分佈式相關的知識,而分佈式的知識浩如煙海,晦澀難懂,如:分佈式協議、分佈式事務,資源協調,Zookeeper等,光這一堆的概念就讓人望而卻步。我們知道,學習一門技術,如果不深入理解背後要解決的問題與設計原理,就很難做到靈活運用,觸類旁通。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這篇文章我們就從服務發現的基本概念入手,再結合Eureka的具體實現,來深入分析服務發現背後要解決的問題與設計原理。"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"這不僅是我們閱讀這個系列文章,學習微服務,學習分佈式系統的必經之路,同時很多的設計理論也可以爲我們學習其他技術(如:Hadoop,區塊鏈等)打下堅實的基礎。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"文章比較長,大約有1萬3千多字,建議大家打開目錄進行閱讀,現在我們就以下面四個問題爲線索,來全面解析Eureka服務發現的原理機制。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"1)如何理解服務發現這一概念?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"2)服務發現要解決的問題是什麼?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"3)Eureka是如何設計服務發現?"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"4)Eureka如何保證高可用與數據一致?"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"一、"},{"type":"text","text":"如何理解服務發現這一概念?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個概念往往是對某一個領域,某個問題的高度概括,要理解服務發現這個概念,我們 從分佈式系統說起,這裏我不想引用百度詞條或專業的術語給分佈式系統下一個定義,這容易讓人產生困惑,我引用一句更通俗易懂的古語來對分佈式系統做個比喻:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":" “當一頭牛拉不動車的時候,不要試圖去尋找一頭更強壯的牛,而是要用兩頭牛來拉” "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,從狹義上來講分佈式系統可以理解爲:"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"由諸多應用程序協同合作來完成任務的一種工作模式系統"},{"type":"text","text":"。這裏的任務可能是一個商品的下單操作,可能是一個超大集合的排序計算,可能是存儲一個超大的文件,也可能是繪製團戰遊戲的實時畫面。總之,這個任務由於各種條件限制,很難由單個程序獨立完成,而需要由多個程序一起協同完成,這種工作模式我們用計算機語言總結有4個特徵:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"1)協同工作的各個程序運行在由區域、機房、機櫃,交換機、網線連接的計算機上;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"2)程序之間通過一次或者多次遠程調用或數據傳遞來完成某項任務;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"3)程序可能會奔潰,硬盤可能會損壞,CPU可能會跑滿,網絡可能會抖動;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"4)任務成功與否由多個程序共同決定,一個程序失敗,可能整個任務都失敗;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看了以上4個特徵,是不是覺得分佈式系統的工作模式有些不靠譜,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"這種工作模式太複雜、充滿不確定性,非常脆弱"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"。"},{"type":"text","text":"這有點像馬戲團小丑的雜技表演,腳下踩着獨輪車,頭上頂着碗,雙手還不停的拋着皮球,這種表演很脆弱,只要任何一個小地方出現閃失,比如某個球沒接住掉到地上,那表演就算失敗。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f6/f69897918d8d9bc942a8798a72ec8336.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分佈式系統也是如此,所有環境,所有程序只要某個環節出現一點問題,都會影響整個任務的執行結果。面對這種不確定性與複雜性,計算機科學家們無論在學術理論還是工程實踐方面,想了很多辦法也沉澱了很多成果,包括:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"抽象提煉問題,如互斥性問題,冪等性問題,拜占庭將軍問題等;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"總結昇華定律,如CAP理論,BASE理論等;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"解決設計算法,如Paxos算法,ZAB算法,分佈式哈希算法等;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"規範定義概念,如服務發現,分佈式事務,負載均衡,配置中心等;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"開發工程工具,如Zookeeper,Eureka,GTS,Apollo等;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"因此我們看到,服務發現在整個分佈式生態中的位置,它是整個分佈式生態中一個十分重要的概念"},{"type":"text","text":",這個概念代表着分佈式中某一個具體的問題域,圍繞這一概念還涉及分佈式生態中其他很多知識,如:CAP的理論基礎,ZAB的算法思想,Zookeepr或Eureka的工程工具等等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"二、服務發現要解決的問題是什麼?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面我們說到,服務發現是爲解決分佈式環境中某問題域而產生的一個概念,那具體是針對哪些問題域,具體要解決哪些問題呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務發現要解決的第一個問題就是--"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"解耦、屏蔽程序之間 IP與端口的依賴。 "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"在分佈式系統工作特徵中我們說過“程序之間通過一次或者多次遠程調用或數據傳遞來完成某項任務\""},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}},{"type":"strong"}],"text":","},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"因此,調用程序方首先要知道被調用程序在網絡中的標識,我們知道在計算機網絡里程序的標識是用"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"IP+端口"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"來實現,但這種方式存在兩個問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"IP與端口沒有任何特殊含義不便於理解、不便於記憶;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"當程序部署的IP與端口改變,程序的調用者也要同步修改;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而通過服務發現,可以將服務之間IP與端口的依賴轉化爲服務名的依賴,服務名可以根據具體微服務業務特徵來命名,因此,屏蔽、解耦服務之間IP與端口的依賴是服務發現要解決的第一個問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務發現要解決的另一個問題是--"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"動態管理程序的狀態"},{"type":"text","text":","},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"在分佈式系統工作特徵中我們說過,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"“程序可能會奔潰,硬盤可能會損壞,CPU可能會跑滿,網絡可能會抖動"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}},{"type":"strong"}],"text":"\","},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"因此,在分佈式環境中程序的狀態是隨時發生變化的,而且從某種程度上來說這種變化不可預測,誰也不知道下一秒某個程序會不會掛掉,一旦某個程序出問題,調用者還未得到通知的話,可能會發生多米勒骨牌式的連鎖反應。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"而服務發現可以對服務的狀態進行實時管理,當程序狀態發生改變時,可以第一時間通知到程序的使用者,我們可以從如下兩個方面去理解這種管理能力。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"首先,程序要能彼此知曉對方的信息與狀態;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"其次,當對方信息與狀態發生變化時要能及時知曉;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"三、Eureka是如何設計服務發現的?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前面我們對服務發現的概念與要解決的問題做了簡單的介紹,這都是爲理解服務發現的設計原理做的鋪墊。下面我們就以Eureka服務發現爲例,來分析一下服務發現是如何設計的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"1、引用一個統一管理中心"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務發現的目標是要抽象程序標識並對程序狀態進行動態管理。一旦涉及到管理,我們第一個想到的是什麼?集權、集中、統一,設置一個機構等等。Eureka也是如此,要管理這些程序,先要有一個統一的管理中心,這個統一的管理中心就是"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"--註冊中心。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"註冊中心可以認爲是Eureka的大腦,肩負着Eureka的各項管理,協調職能"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用統一的管理中心這一設計思想,在分佈式架構中幾乎無處不在,如Hadoop,Zookeeper等等。而作爲對比的非統一中心設計思想,就是比特幣,比特幣中的節點程序除了在功能上有所區分(如錢包節點,挖礦節點)在職能上沒有任何特殊的中心節點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"2、定義四個基礎概念"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"理清服務端、客戶端、生產者,消費者四個基本概念"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將註冊中心作爲服務發現中的管理者是個不錯的主意。就像公司一樣,從職責上對員工進行劃分,比如:出錢的--老闆,找活幹的--產品經理,監督幹活的--項目經理,正真幹活的--程序員,背鍋的--初級程序員。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了理解溝通方便,服務發現對管理者與非管理者也進行了劃分,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"負責管理的註冊中心--服務端,負責具體完成任務的程序--客戶端"},{"type":"text","marks":[{"type":"italic"},{"type":"color","attrs":{"color":"#FF7021","name":"orange"}},{"type":"strong"}],"text":","},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"這就是服務器端與客戶端的概念。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過服務端與客戶端的概念,從職責上對程序進行了區分,但是,對於具體幹活的客戶端,還有一個問題:那就是它們之間的調用關係錯綜複雜,能不能從調用關係這個維度對客戶端再進行區分呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答案是肯定的,因此,對於客戶端又分爲生產者,消費者的概念。例如,一個任務需要兩個程序協調合作,程序A調用程序B,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"調用方也就是程序A叫--消費者,被調用方也就是程序B叫--生產者。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"生產者與消費者只是概念上的區別,它們並不是單獨的兩類程序而是一類,都屬於客戶端。一個程序是不是生產者與消費者並不是絕對的,可能是生產者,可能是消費者,也可能既是生產者也是消費者,這取決於我們看待的角度。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ef/efbe6ccc7c155a74f2a3b9b3afd2e080.png","alt":null,"title":"服務器端、客戶端、生產者、消費者","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"服務端,客戶端、生產者、消費者這四個概念非常重要"},{"type":"text","text":",在涉及服務發現的文章中(包括本文,網上或者相關書籍)都會被大量重複提及。我們要結合上下文去理解這些概念,否則碰到一段話就很難看懂,甚至會被誤導。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"3、抽象七個基本運行流程"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"理順了相關的概念之後,下面我們重點來介紹Eureka服務發現的基本運行流程,這會使我們對Eureka有一個初步的整體認識,這是理解後面更復雜內容的前提,也是進一步研究源碼的基礎。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我將Eureka基本運行流程抽象爲七個步驟,當然這七個步驟並不是嚴格的順序執行,更不是官方的說法,只是讓我們更好的理解Eureka的工作流程,這7個步驟分別如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"1、客戶端發起服務註冊;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"2、服務端保存信息至註冊表;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"3、客戶端定時發送心跳請求;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"4、服務端服務剔除與自我保護"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"5、客服端發送服務下線請求"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"6、客戶端獲取服務端註冊表;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"7、客戶端整合服務發現;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ff/fff9e8edb7cdac788dd826ae91357d64.png","alt":null,"title":"Eureka整體運行流程","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"1、客戶端發起服務註冊"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"客戶端向服務器發送請求,將自身的相關信息提交給服務端;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"對於這一步驟很好理解,即當客戶端程序啓動時,先要加入到分佈式系統中,第一步就是要向服務器提供自身的信息並告訴服務端我來了。這跟婚介所有點像,你想在婚介所找對象,就得先到婚介所登記提供自己的詳細信息,只有這樣女孩子纔可能瞭解到你。在服務發現中這一過程就叫"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":" --服務註冊"},{"type":"text","marks":[{"type":"italic"},{"type":"size","attrs":{"size":12}},{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那Eureka是如何實現服務註冊這一過程的呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務端提供一個對外註冊接口,用來接收客戶端的註冊請求,服務端啓動後會一直監聽這個接口,等待客戶端調用;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"客戶端在啓動時,先找到服務端與自身的配置信息(分區,名稱,IP,端口等),再調用服務端的註冊接口將相關信息發送給服務端;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關於配置信息可能在客戶端程序的配置文件中,也可能在統一的配置中心,配置中心在這個系列文章中我們會詳細介紹。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/2f/2f92e49defebfd28cc87894bc53c4e9f.png","alt":null,"title":"客戶端服務註冊子流程","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"2、服務端保存信息至註冊表"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務端將客戶端提交的註冊信息保存至本地內存註冊表;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這一步驟很簡單,也沒有任何流程與通信。但這裏的"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"註冊表"},{"type":"text","text":"可能是Eureka中最核心,最關鍵的概念,註冊表的作用就跟數據庫一樣,不管是我們正在討論的7個基本運行流程,還有後面要說的數據同步操作等,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"其本質就是圍繞着對註冊表添加、更新、刪除、獲取,同步等一系列操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"註冊表這麼重要,那註冊表到底長什麼樣,存儲了哪些數據呢?其實,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"user"}}],"text":"Eureka註冊表是一個雙字典結構的數據"},{"type":"text","text":", 服務發現的目標是標識與管理服務的狀態,因此註冊表裏面存儲的有服務標識,服務基本信息,服務狀態等數據,如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/03/03da245ae372c265a31ba862a9e3adfd.png","alt":null,"title":"註冊表雙字典結構","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"}],"text":"本篇文章,我本不打算加入任何源代碼,後面計劃是寫一篇專門對Eureka源碼分析的文章。但是,這裏要理解註冊表的雙字典結構,最高效的方式還是直接看看源碼的定義,如下代碼:"}]},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"ConcurrentHashMap>> registry\n = new ConcurrentHashMap>>();"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼是字典結構,而且還是雙字典結構呢?在大型系統中一個業務服務由多個實例程序進行負載,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"當對某個實例程序信息進行操作時,只要通過服務標識Key找到多個服務實例,再通過服務實例標識Key找到該實例信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"這種操作的時間複雜度爲"},{"type":"text","text":"O(1)效率非常高。當然,Eureka爲了追求極致的效率,還配合使用了一些緩存機制,有機會我們會詳細分析。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"3、客服端定時發送心跳請求"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"客戶端定時向服務端發送請求告訴服務端我還活着"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼要有這一步驟?如果客戶端只是在啓動時註冊自己,在後續的程序運行中,程序宕機或者其他異常,服務端是不知道的,服務端就達不到實時狀態管理的目的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此,需要客戶端不時的主動發送請求告訴服務端-我還活着,服務端再根據上報情況進行判斷,哪些程序正常,哪些程序不正常,這種主動上報的方式在Eureka中叫 "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"--服務續約。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在具體實現上,Eureka在服務端開放一個續約接口,用來接收客戶端的心跳請求。"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"客戶端啓動一個定時器,定時調用服務端的續約接口"},{"type":"text","text":",服務端接收到請求後,更新自己註冊表中服務實例的續約時間,如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3c/3c39490c125b06e6cfb07c4dbb6f9ae4.png","alt":null,"title":"心跳續約機制","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在分佈式系統中這種定時心跳續約的方式叫"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"user"}}],"text":"--Lease 機制,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"Lease機制有很多應用場景,比如Eureka中服務剔除,"},{"type":"text","text":"密鑰更新,分佈式文件系統的順序號等。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實在大型的分佈式環境下,這種簡單的心跳續約還不夠,比如有一個程序CPU跑到了98%,這臺服務器已經在崩潰的邊緣,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"但是它並沒有掛掉,心跳續約也正常,服務端會判斷是正常服務"},{"type":"text","text":",這樣在負載分配策略上就會有很大的問題,關於負載均衡,在這個系列文章中我們會單獨介紹。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"4 、服務端服務剔除與自我保護"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務端在一段時間內未收到客戶端心跳請求,就從註冊表中移除該客戶端"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面我們說了心跳續約,客戶端主動續約自己狀態,服務器端維護最後的續約時間,這樣做目的只有一個,就是讓服務端來判斷客戶端服務是否運行正常。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"如果服務器端在一定時間(默認90秒)內沒有收到客戶端的心跳續約"},{"type":"text","text":",那麼服務端就認爲該客戶端可能掛掉了,就將客戶端實例從註冊表中移除,消費者客戶端便拿不到異常的服務實例,這個過程就叫"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"--服務剔除。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"size","attrs":{"size":12}},{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}},{"type":"strong"}],"text":"服務自我保護"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"關於服務剔除還有一種特殊情況,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"當網絡發生了故障,客戶端與服務端暫時無法正常通信"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"。但是客戶端實例運行正常,生產者與消費者之間通信也正常,服務消費者也可以調用服務生產者。如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"​"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9d/9d04b0d718fd50f790273f751e0946cb.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"如果按正常的服務剔除邏輯,那些沒有正常續約的客戶端,會被從註冊表中剔除掉,這樣會影響那些正常網絡內的客戶端。對此,Eureka有一種自我保護模式,默認是"},{"type":"text","text":"打開狀態,具體操作我總結爲如下幾點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務端判斷15分鐘之內超過85%的客服端都沒有心跳續約,則自動進入自我保護狀態;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"進入自我保護狀態後,服務端不再剔除沒有繼續續約客戶端;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"進入自我保護狀態後,服務端只接受新客戶端的註冊操作與服務查詢操作;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"自我保護模式是Eureka設計的一種自我容錯策略"},{"type":"text","text":",它將網絡異常或抖動對系統的影響降到最低,增強了系統的穩定性與健壯性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"5、客服端發送服務下線請求"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"如果客戶端正常關閉,則向服務端發送已下線請求,服務端直接從註冊表中移除該客戶端"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Eureka運用服務心跳續約、服務剔除來鑑別、排除異常的客戶端服務。那對正常關閉的客戶端呢?比如做灰度發佈時主動關停部分服務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這種情況下,如果等待服務續約失敗再執行服務剔除操作,整個流程就太複雜、效率也太低,畢竟從客戶端程序關閉,到心跳續約停止,再到服務器端檢測異常剔除,會有一定的延遲時間。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此, 當客戶端正常或主動關閉時,則主動向服務端發送下線請求,服務端收到請求後從註冊表中移除該客戶端,這一系列操作就"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"--服務下線。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"6 、客戶端獲取服務端註冊表"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"客服端定時向服務端獲取註冊表信息,並保存至本地註冊表中"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以上說的幾個步驟,都是在講生產者如何與服務端進行通信。那對於消費者呢?消費者跟服務端具體有哪些操作?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對消費者來說與服務端之間的通信非常簡單,即通過服務端獲取生產者的服務註冊信息,來完成後續的業務調用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"在設計上消費者本地也有一個註冊表,還有一個定時器,每隔一段時間客戶端向服務端發起請求,用來獲取服務端註冊表信息,並將獲取來的註冊表信息,同步到自己的本地註冊表中,如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e8/e8e905ba934e115095752a10f3266ab4.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏還有一個細節問題,如果客戶端本地註冊表中的數據,跟服務端獲取來的數據存在衝突怎麼辦?關於這些問題我們在後面章節高可用與數據一致性時會講到。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"7 、客戶端整合服務發現"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"客戶端消費者從本地內存中獲取生產者服務信息,並執行後續的調用操作;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於這一步驟,嚴格來講不算是Eureka的範疇,但如果少了這一步,我們理解服務發現就會大打折扣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"文章的開始我們就提到服務發現要解決的問題,但我們一直在講Eureka有哪些概念、是如何設計的等等,卻沒有講服務發現具體是如何解決這些問題,即應用程序如何整合服務發現,最終完成服務間相互調用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這好比我們有一把斧頭,我們總是誇它用了多好的鋼鐵,是如何一步一步製造出來的,但卻不告訴人們如何用它來砍樹,也好比畫了一條龍,最後忘記畫眼睛。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"大家目前只要知道有這麼回事就行,在這個系列文章中,我會結合服務網關Zuul來講解這塊內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"最後,我將Eureka整體運行流程的7個步驟畫到一張圖上,如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ff/fff9e8edb7cdac788dd826ae91357d64.png","alt":null,"title":"Eureka整體運行流程","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":3}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"四、Eureka如何保證高可用與數據一致?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"前面的篇幅,我們從服務發現運行流程的角度,將Eureka核心設計抽象爲7個流程步驟,並對每一步驟進行了簡單的闡述。但是,我們忽略了一個重要問題,我們討論的所有流程中,註冊中心只有一個,並未涉及到多個註冊中心的內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}},{"type":"bgcolor","attrs":{"color":"#ffffff","name":"user"}}],"text":"事實上Eureka的註冊中心是支持集羣運行的,即運行多個服務端實例,這些實例可以部署到不同的區域、機房。這樣可以橫向擴展服務發現的規模,當某個服務端實例掛掉之後,整個服務發現還能正常運行,保證系統的高可用。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"集羣運行,高可用無論在設計上還是實現上都不是一件簡單事情,要付出相當大的代價,在某些條件下甚至只能選擇妥協,如google在最早的hadoop1.x的版本中,就只設計了單個NameNode,Hadoop1.x存在單點故障問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那針對Eureka支持多註冊中心的集羣運行方式,具體有哪些挑戰呢?至少有兩個問題要解決:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"1、從服務器端來說,如何保證各個服務端數據的一致性;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"2、從客戶端來說,應該選擇哪個服務端進行通信;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"接下來的篇幅我們都將圍繞着這兩個問題展開。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"1、一個關於CAP理論的故事"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們剛纔說到了系統高可用,數據一致性,這些話題不僅僅是Eureka服務發現要面臨的問題,而是所有分佈式系統都要面臨的問題,爲此我們要先理解一個定律"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"--CAP定律"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼有這個理論?這個定律說的到底是什麼?讓我們從下面的一個故事說起。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/82/827fd97a66694e4250f67578887c71f8.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在一個大型分佈式系統中,多個節點程序部署在網絡連通的5個機房內,節點們各司其職,系統就這樣一直安靜、穩定的運行着......."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然而,一隻老鼠的出現打破了一切美好的現狀。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"某天夜裏,一隻飢餓的老鼠尋找食物,闖進了A機房防潮隔離層內,並把機房連通外界的光纜啃斷了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"顯然,A機房與其他機房失去了連接,整個網絡也被分成了兩塊區域,一塊A機房區域,一塊非A機房區域(如下圖所示)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/00/00c0493162e081c313526a3a225cbc48.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"情況出現之後,團隊圍繞系統是否還要正常工作,展開了一場頭腦風暴。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" "},{"type":"text","marks":[{"type":"strong"}],"text":"老闆說:"},{"type":"text","text":"“ 老鼠啃網線這很正常,我們不能對老鼠有過分的期望,必須要應對這種突發事件,因此,系統必須要正常工作,用戶不關心老鼠與機房的任何事情”。叮叮......老闆電話響了,“你們先研究討論一下,相信你們一定能解決這個問題”,於是,老闆拿着手機走出了會議室。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"程序員小周眉頭緊皺:"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"“這可能有點困難,因爲A機房有個程序,裏面存放着非常重要的數據,其他程序都得用到這個數據,缺少了這些數據,整個系統肯定是跑不起來”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“我不管,這是老闆的要求!今天必須解決這個Bug”。有人賣掉一個腎,切掉一半胃,都能活得好好的,爲什麼我們系統被老鼠吃掉一段網線就不能運行呢?”。"},{"type":"text","marks":[{"type":"strong"}],"text":"產品經理理直氣壯的說到。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"會議室被一股尷尬的氣氛籠罩着,程序員小周實在忍不住想笑。 \"產品經理居然認爲這是一個bug,關鍵是他的這個比喻.....莫非是得到了郭德綱的真傳?\" 。但是 ,看着產品經理一本正經的表情,他用拳頭捂住嘴巴故意咳嗽了幾聲,硬是把笑意憋了回去。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"架構師老陳"},{"type":"text","text":"翹着二郎腿,不停的摸着他那非洲稀疏草原似的頭頂,一副若有所思的樣子,大家把目光都投向他,等待着他的回答:"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"“解決方案也是有的,只要我們將A機房的程序,在每個機房都部署一份,同時保證這些程序之間的數據一致,如果A機房不可用,那我們就用其他機房程序裏的數據”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"小周仰望着天花板,突然,他猛的拍打了一下自己的大腿,從椅子上躍了起來,擼起襯衫的袖子,這件藍色方格子襯衫,他連續穿了不少於3個星期,他說到:“"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"是啊,我怎麼沒想到呢?我們把數據同步到其他機房不就OK了嗎?”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還沒等大家反映過來,小周已衝出會議室,只聽見辦公室裏“嗒嗒......嗒嗒......“,青軸鍵盤發出悅耳的歌聲。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"10個小時之後,程序修改大功告成,發佈上線,與此同時,客服辦公室的電話已被打爆......."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶反映系統某個操作完全沒有反應,團隊又開始了新一輪的頭腦風暴。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這次老陳先說話了,“小周,你那個代碼是怎麼寫的,改出bug了啊”。 程序員小周開始爲自己辯解到:“沒理由!不至於啊! 你不是說要將A機房的數據同步到其他機房,還要保證數據一致性嗎,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"我就在處理A機房數據操作時,加入了同步其他機房的代碼,爲了確保數據一致,我讓所有的機房更新數據返回成功之後,再執行下面的操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"老陳繼續摸着他那非洲稀疏草原似的頭頂,接着問了第二個問題,那假如C機房的網線也被老鼠啃了,對C機房接口的調用不會成功也不會失敗,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"而是出現第三種狀態--超時"},{"type":"text","text":",那你的處理有什麼問題呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"程序員小周工作不到2年,有點愣頭青,幹活積極,思維敏捷,通過老陳的一番點撥,他立馬就明白了問題所在。他迴應到:“是啊,爲了保證數據一致性,我將所有接口返回成功作爲條件,結果就是,一旦有某個接口返回失敗或者超時,整個業務操作就沒法進行了”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"小周接着說道:"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"“爲了保證網絡分區後系統能正常使用,就得將數據同步到更多的機房並保證數據一致,爲了保證數據一致,就得保證每個機房都同步操作成功,但是,反過來假如有一個機房返回失敗或超時,整個操作就算失敗,這又影響了系統的可用性 ”。"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"分區可用,數據一致,可用性這三者 就像先有蛋,還是先有雞的問題,好南啊”!"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"老陳滿意的點了點頭心想到--"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"user"}}],"text":"後"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"浪可謂啊!"},{"type":"text","text":"他又清了清嗓子對小周說到:“你理解得很到位,在分佈式系統中,分區容錯性,數據一致性,可用性這三者是一個矛盾體,就好像我們不能“又想當什麼什麼,又想立牌坊”,在這三者之間,我們必須要有所取捨。而且,這是有理論作爲依據的,那就是CAP理論。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"故事到這裏就講完了,純屬瞎編,我們再來看看CAP理論的內容:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"一致性(Consistency)"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":" "},{"type":"text","text":"(數據在多副本的情況下,對數據進行更改操作時,可能因爲機器,網絡或其他原因,一部分副本更改成功,一部分副本更改失敗,導致數據的不一致)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"可用性(Availability)"},{"type":"text","text":"(在任何時候客戶端對集羣進行讀寫數據操作時,集羣必須在一個規定的延遲內返回結果——但是,不能保證返回的數據是最新的)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"分區容錯性(Partition tolerance)"},{"type":"text","text":"(所謂分區容忍是指:當網絡發生故障,整個集羣被劃分爲多個無法相互通信的區域時,系統任然可用)"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a3/a34505ba40cdd3595dc0f9d1a092f464.jpeg","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結來說就是,數據存在的節點越多,分區容忍性越高,但是複製更新的節點就要越多,複製的節點越多一致性就越難保證,爲了保證一致性,更新所有節點數據所需要的時間就會越長,時間越長系統可用性又會降低。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於一致性、可用性、分區容忍性這三者,我們很難同時都滿足,只能有所側重的去滿足其中1點或者2點,這就是CAP理論的核心內容。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"CAP理論爲分佈式系統設計提供了理論依據,它告訴我們不可能設計一個十全十美,包羅萬象的分佈式系統,就跟能量守恆定律告訴我們不可能製造出永動機一樣。系統架構設計的精髓在於權衡,取捨,與適應。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"2、可用性與一致性的取捨"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"剛纔我們通過一個故事對CAP理論做了簡單的分析,那Eureka的設計是如何遵循CAP定律的呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先對於服務發現,網絡分區客觀存在,我們沒法改變,出現網絡分區後系統肯定也要能正常運行,也就是上面故事中老闆的要求。因此,這裏我們討論CAP理論時,是以分區容錯性爲前提,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"然後再來談系統是CP類型,還是AP類型,即在分區容錯性基礎上再權衡一致性(C)與可用性(A)。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Eureka選擇的是AP優於CP的原則,即可用性優於一致性,爲了更好的理解Eureka的AP設計原則,以及CP與AP之間的差異,我們將Eureka與Zookeeper做一個對比分析,看看它們在CP與AP之間是如何取捨的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b5/b5bba460fbbf3de3e1d675ff1a94c51b.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","text":"​Zookeeper CP系統"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如上圖所示,整個ZK集羣部署在兩個機房內,其中ZK Leader部署在機房1,兩個機房還分別部署了ZK Follower、生產者與消費者。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於某些原因導致兩個機房的網絡中斷,即出現了網絡分區。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於Zookeeper CP系統,此時當機房2中的生產者B進行註冊時不會成功,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"因爲,CP系統要求的是強一致性,ZK要保證數據成功同步到其他的Follower節點,也就是機房2中Follower的數據要成功同步到機房1 的Leader之後,才認爲註冊成功。"},{"type":"text","text":"顯然,此時做不到,因爲兩個機房的網絡中斷了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然而,機房2中的生產者與消費者之間連接正常,它們應該是可以在機房2中註冊成功,並完成遠程調用。但是,Zookeeper爲了集羣數據的強一致性,犧牲了機房2的可用性,這就是CP系統的特徵,優先考慮數據一致性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們再來看Eureka AP 可用性優先會如何處理?當網絡分區後,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"Eureka會先允許機房2內的服務註冊成功,機房2中消費者也可以調用生產者,網絡分區後機房2中的可用性絲毫不受影響,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":" 其代價就是機房1與機房2中的數據會不一致"},{"type":"text","text":",這就是AP系統的特徵,爲了可用性犧牲部分數據一致性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那Eureka爲什麼要選擇AP呢?個人認爲,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"服務發現中服務器的數據屬於客戶端的元數據(IP,端口、狀態),元數據並不會像業務數據那樣頻繁變化,導致數據不一致的機率沒那麼高,拿到一份過期或不一致的數據,總比拿不到任何數據要強。"},{"type":"text","text":"並且,當客戶端拿到服務數據進行服務調用時,自身也會做相關其他的處理,比如:重試、熔斷、負載等,這些我們也會在這個系列文章中介紹。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"3、服務端如何實現數據同步?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們繞了一大圈講CAP理論,講Eurkea如何選擇AP等等,下面我們就具體來分析Eureka是如何進行服務端數據同步的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"1、Peer To Peer 同步模式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一般而言,分佈式系統中的數據同步模式可分爲兩種:主從模式,對等模式。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}},{"type":"strong"}],"text":"主從模式(Master-Slave):"},{"type":"text","text":"在集羣有一個主副本與多個從副本,所有數據的寫操作都提交到主副本上,最後再由主副本更新到其他從副本,而從副本負責所有的讀操作。該模式主副本節點要承擔所有的寫入壓力,可能會成爲系統的瓶頸,但是數據的一致性能得到保證。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}},{"type":"strong"}],"text":"對等模式(Peer To Peer):"},{"type":"text","text":"在集羣中不分主從,任何副本都可以進行讀寫操作,副本與副本之間實現數據同步,這樣的優點是:不存在任何單點的寫操作壓力,缺點是:每個副本都可以進行寫操作,數據同步與解決數據衝突就成了一個棘手的問題。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"2、數據同步操作"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面討論的兩種數據同步模式中,Eureka選擇對等模式來實現服務端集羣註冊表的信息同步。具體來看一個例子,假如Eureka服務端集羣由4個服務端構成,當某個客戶端跟服務端A進行通信時(註冊,下線,剔除),該服務端A註冊表會發生變化,此時服務端A會將這些操作同步到其他B、C、D3個服務端,從而保證整個集羣的數據一致,如下圖所示:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"還有一種情況,當新的服務端準備加入集羣時,集羣中其他服務端註冊表已經有完整的註冊信息,如果新服務端再等待其他服務端的數據同步操作,那隻能獲取部分數據,新服務端的數據就會丟失,因此,當新的服務端加入集羣時,先要去某個服務端獲取全部的註冊表信息。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b7/b78584d79840f2c565e62c0ab7481542.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏的操作是不是很熟悉,數據同步的操作跟我們講Eureka7個核心步驟的操作很相似,是的,服務端集羣雖然在職責上叫服務端,但是爲了實現集羣數據同步,在操作上跟客戶端的那些操作(如:服務獲取,註冊、下線、剔除等)又是一樣的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實,Eureka服務端要依賴客戶端,但是這裏講的客戶端不能直接等同於上面在“定義四個基礎概念”所說的客戶端。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那裏所講的客戶端是從業務角度去理解,即客戶端是包含業務代碼的程序,具體幹活做業務操作的,而這裏的客戶端是從集羣通信的角度來說,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"因爲Peer To Peer 模式 ,沒有中心服務端,也就沒有客戶端,所以,從通信上來說Eureka的服務端同時又是客戶端。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"user"}}],"text":"某些概念放在不同的上下文中,所代表的內容與含義會完全不一樣"},{"type":"text","text":",因此要理解這些概念,我們一定要先看看上下文說的是什麼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"3、如何避免死循環?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們還是回到剛纔的數據同步問題,大家是否思考過這些問題,假如:客戶端對服務端A進行了下線操作,服務端A將操作同步到B、C、D其他3個服務端,當服務端B接收到同步過來的下線請求後,會不會再將該操作又同步到其他的服務端,從而使同步陷入死循環呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"答案是不會,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"Eureka會區分正常的客戶端請求與服務端發起的數據同步請求,對於任何服務端發起的數據同步請求,Eureka不會再進行其他同步操作,從而避免數據同步出現死循環。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"具體的做法是Eureka在http請求頭中加入特殊的標識,用來區分正常的客戶端請求與數據同步請求。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"4、如何解決數據衝突?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"剛纔說了數據同步的流程與如何避免數據同步陷入死循環,但是在數據同步的過程中還有一個重要的問題要解決"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"--那就是數據衝突"},{"type":"text","text":"。數據衝突有兩層含義:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"第一是:如何標識數據衝突,即誰的數據新,誰的數據舊;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"第二是:當發生了衝突後怎麼使用數據,如何解決衝突;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}},{"type":"strong"}],"text":"1)使用版本號解決數據衝突"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於第一個問題很好解決,一般我們給數據加一個版本號就行,如時間戳,只要有任何數據更新操作,就更新時間戳,最後更新數據的時間戳最大,也就是最新的數據,上面講Eureka中註冊表中時間信息就是做此用途的。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於第二問題就要稍微麻煩一些,我們可以從一個場景來說:當服務端A向服務端B同步數據時,發現A,B都有這條數據,但是各自數據的時間戳不一樣,即發生了衝突,那無非就兩種情況 "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"A新B舊,B新A舊"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"先看第一種情況 "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"A新B舊,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":" 如下圖:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/48/48c40600ae7582540415ebe0fbe3843e.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當服務端A向服務端B發起同步請求時,服務端B發現自己不是最新的數據,於是返回一個404狀態,服務端A發現返回狀態是404時,則從新發起一個服務註冊同步請求,服務端B接收到註冊請求後則同步數據。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再來看第二種情況 "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"B新A舊"},{"type":"text","text":" ,如下圖:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/18/185c63d83261be74d1511290f2e55079.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當服務端A向服務端B發送同步請求時,服務端B發現自己的數據比服務端A的要新,於是返回409狀態,告訴服務端A我的數據是最新的,服務端A收到返回409時,則向服務端B發起獲取數據的請求,服務端B返回最新的數據。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}},{"type":"strong"}],"text":"2)客戶端定時獲取註冊表並檢測數據"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"剛纔我們說的是通過版本號來解決數據衝突問題,這有點像事後補救措施,在同步過程中發現數據衝突再解決,但是如果某個數據同步操作失敗了,數據衝突還是會存在。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"其實Eureka還有一種更主動的方式來解決數據衝突,那就是在客戶端通過心跳請求來獲取服務端註冊表數據,如果發現與本地數據存在衝突,則讓有衝突的客戶端從新執行註冊操作。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"4、客戶端選擇哪個服務端通信?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們再來回答這個章節的第二個問題 :"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"“當有多個服務器端時客戶端選擇與哪個服務端進行通信?”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}},{"type":"strong"}],"text":"優先使用默認配置"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"首先,客戶端可以配置默認優先的服務端"},{"type":"text","text":",比如客戶端與服務端在同一分區或同一機房時,我們可以指定客戶端優先與這些服務端通信。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}},{"type":"strong"}],"text":"從可用服務端列表中選擇"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果沒有配置默認優先的服務端,客戶端同時還維護着兩個服務端列表,一個不可用列表,一個可用列表,當要與服務端通信時,先從可用列表中選擇一個服務端,並嘗試與該服務端進行通信,如果連續通信3次都失敗,則從可用列表中選擇一個新的服務端從新嘗試。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}},{"type":"strong"}],"text":"隨機打亂可用服務端列表"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務端列表的順序默認是配置文件的順序,每次取服務也變成有順序的了,這樣導致客戶端會選擇排在前面的服務端,從而導致服務負載嚴重失衡,爲此客服端設置了一個定時器,定時器會定時隨機打亂服務列表的順序,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#D46B08","name":"brown"}}],"text":"從而保證客服端隨機選擇服務端,使各個服務端的負載保持均衡。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最後,我將Eureka的整體運行機制放到一張圖上,如下圖:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b6/b606ac85ca4a842697a6ed3341f9ba88.png","alt":null,"title":"Eureka整體運行機制","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"5、Eureka分區(Region與Zone)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"關於Eureka的高可用內容,還有一個問題需要討論,那就是當系統規模比較大,用戶在地理上分佈廣泛時,一般通過將服務部署到多個區域,多個機房,來保證系統高可用、容災,數據靠近用戶等,那Eureka具體是如何支撐分區域,分機房部署與調用的呢?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當服務調用發生在多個機房之間,我們希望同一個機房內的服務優先調本機房內的服務,只有同機房服務不可用時,再考慮調用其他機房的服務,這樣可以最大限度的降低延遲與開銷。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Eureka通過Region與Zone實現了服務的分區管理,Region與Zone這兩個概念都來自亞馬遜的AWS。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}},{"type":"strong"}],"text":"region:"},{"type":"text","text":"可以理解爲地理上的分區,比如亞洲地區、華北地區,北京地區等等,地區沒有具體大小的限制。根據具體的情況自行合理劃分region。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}},{"type":"strong"}],"text":"zone:"},{"type":"text","text":"可以理解爲region內的具體機房,比如說region劃分爲北京,然後北京有兩個機房,就可以在此region之下劃分出zone1,zone2分別代表機房1,機房2."}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於Eureka的分區管理(Region、Zone)可以總結歸類如下幾點:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}}],"text":"Eureka通過分區管理,實現不同區域不同機房服務之間的就近調用,以降低延遲;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}}],"text":"Region表示區域、Zone代表機房,它們之間是一對多的關係;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}}],"text":"可以在服務端與客戶端配置Region與 Zone,將服務指定到不同的區域與機房;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#3399ea","name":"user"}}],"text":"在服務調用時,優先順序選擇配置的Region與Zone;"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"black"}}],"text":"五、總結"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文從幾個問題出發,說明了服務發現的概念,來源於分佈式系統,並簡單介紹了服務發現要解決的問題,還重點介紹Eureka是如何設計服務發現的,並將服務發現的運行流程,抽象爲7個具體的步驟。後面又介紹了Eureka如何保證高可用與數據一致,同時還通過一個故事講解了CAP理論,最後,還談到了Eureka如何實現數據同步,如何實現分區調用等話題;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"這篇文章的主要內容我總結如下:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務發現是在分佈式系統環境下產生的一個基本概念;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務發現要解決的是服務標識與服務狀態管理的問題;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務端,客戶端,消費者、生產者這四個基本概念,是從不同的角度來描述服務發現;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"服務發現基本的運行流程,可以抽象爲7個基本運行步驟;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"Eureka服務端支持集羣部署與運行,支撐高可用與可擴展;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"Eureka服務端集羣採用AP優於CP的設計原則;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"Eureka使用點對點模式來完成服務端集羣的數據同步;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#40A9FF","name":"blue"}}],"text":"Eureka使用Region與Zone的概念對服務分區進行管理,解決服務就近調用的問題;"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分佈式與Eureka的內容繁多,而本人水平有限,如有不到之處還請大家諒解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"italic"},{"type":"strong"}],"text":"微服系列文章"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第1篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/83386f6d764984f3b64b760fb","title":""},"content":[{"type":"text","text":"“四個維度” 講明白什麼是微服務!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第2篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/e4c9866b723b7c4f9cc272050","title":""},"content":[{"type":"text","text":"微服務涉及的技術生態有哪些?"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第3篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/13a6973621381b27bbcd9ab45","title":""},"content":[{"type":"text","text":" 微服務-爲什麼要有服務發現與註冊?"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第4篇: "},{"type":"link","attrs":{"href":"https://xie.infoq.cn/article/c6139a5776e139d1b76b2e856","title":""},"content":[{"type":"text","text":" 萬字長文,助你吃透Eureka服務發現機制!"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章