? ? ? ? 【微服務>>>注冊中心】
? ? ? ? 一、簡介
? ? ? ? Eureka是Netflix公司開源的服務發現組件,其完整體系包含兩個部分,Eureka Server 和? Eureka Client。
? ? ? ? Eureka的目標是一方面給內部服務做服務發現,另一方面可以結合ribbon(負載均衡)組件提供各種個性化的負載均衡算法。
? ? ? ? 二、服務發現技術選型
? ? ? ? Eurake Server端采用的是P2P的復制模式,屬于AP模式,因為它不能保證復制操作一定能成功,因此它提供的是最終一致性。
? ? ? ? Eureka的Server端和Client端采用 心跳 + 租約 的機制來保障有效溝通,Cilent端在Server端的注冊信息有一個帶期限的租約,一旦Server端在指定期間沒有收到Client的心跳信息,那么Server端就會認為Client端注冊的服務是不健康的,定時任務會將其從注冊中刪除。
? ? ? ? 采用Eurake的理由:
? ? ? ? 1? 選擇AP而不是CP,原因后面會闡述;
? ? ? ? 2? 對Java語言體系的團隊更友好;
? ? ? ? 3? Eureka屬于Netflix一部分,和其它Netflix的組件融合的很好,形成一套閉環的微服務架構。
? ? ? ? 三、Eurake的核心對象
? ? ? ? Eureka一共有4個核心對象,下面一一介紹:
? ? ? ? 1? InstanceInfo對象:代表服務的注冊實例;
? ? ? ? 2? LeaseInfo對象:代表應用實例的租約信息;
? ? ? ? 3? ServiceInstance接口:約定了服務發現實例應該有哪些通用的信息;
? ? ? ? 4? InstanceStatus枚舉:用于標識服務實例的狀態。
? ? ? ? 四、服務的核心操作
? ? ? ? 對于服務發現來說,圍繞服務實例主要有如下幾個重要的操作:
? ? ? ? 1? 服務注冊(Register)
? ? ? ? 2? 服務下線(Cancel)
? ? ? ? 3? 服務續租(Renew)
? ? ? ? 4? 服務剔除(Evict)
? ? ? ? 圍繞這幾個重要功能,Eureka設計了幾個核心操作類,其中LeaseManager和LookupService是Eureka關于服務發現相關操作定義的接口類,前者定義了服務寫操作相關的方法,后者定義了查詢操作相關的方法,其中LeaseManager中定義了應用實例在服務中心的幾個操作方法:register、cancel、renew和evict,LookupService則定義了Client從服務中心獲取服務實例的查詢方法。
? ? ? ? 五、Eureka的設計理念
? ? ? ? 作為一個服務注冊、服務發現中心,Eureka主要解決以下幾個問題:
? ? ? ? 1? 服務實例如何注冊到服務中心
? ? ? ? 在Client服務啟動的時候,需要調用Eureka的Rest API 的 register方法,去注冊該應用實例的信息。
? ? ? ? 2? 服務實例如何從服務中心刪除
? ? ? ? 正常情況下服務實例在關閉應用的時候,應該通過鉤子方法或其他生命周期回調方法去調用Eureka Server的 Rest API 的 de-register方法,來刪除自身服務實例的信息。另外為了解決服務實例掛掉或其他異常情況沒有及時刪除自身信息的問題,Eureka Server 要求 Client端定時進行續租,也就是發送心跳,來證明該服務實例還活著,并且可以健康的提供服務。如果超過租期一定時間后還沒有續租的話,Eureka Server端會主動剔除,這是典型的心跳模式場景。
? ? ? ? 3? 服務實例信息的一致性問題
? ? ? ? 下面主要從三·個方面來闡述Eureka Server集群如何保持一致性:
? ? ? ? 3.1??AP 優于 CP
? ? ? ? 分布式系統的設計都是在AP和CP之間進行選擇,Eureka的設計者認為,大規模集群條件下,失敗是不可避免的,無論什么原因,都不能回避這個問題,要面對這個問題,就需要在網絡分區的時候,還能夠正常提供服務注冊、服務發現功能,因此Eureka選擇了AP。其實在實際生產環境中,注冊中心保留可用及過期的數據總比丟失掉可用的數據好。所以,應用實例的注冊信息在集群的所有節點間并不是強一致的,這就需要客戶端能夠支持負載均衡及失敗重試。在Netflix生態中,由ribbon提供這個功能。
? ? ? ? 3.2? Peer to Peer 架構
? ? ? ? 一般而言,分布式系統的數據在多個副本之間的復制方式,可分為主從復制和對等復制。
? ? ? ? 主從復制也就是Master-Slave模式,即有一個主副本、其他副本為從副本。所有對數據的寫操作都是先提交到主副本、然后主副本再更新到從副本。具體更新方式有同步、異步、同步異步混合。對于主從模式來講,最大問題在于寫操作的壓力都在主副本上,它是整個系統的瓶頸,但是從副本可以幫助主副本分擔讀請求。
? ? ? ? 對等復制即Peer to Peer的模式,副本之間不分主從,任何副本都可以接收寫操作,然后每個副本之間相互進行數據更新。對于對等復制模式來講,由于任何副本都可以接收寫操作請求,所以不存在寫操作壓力的瓶頸。但是由于每個副本都可以進行寫操作處理,各個副本之間的數據同步及沖突處理是一個比較棘手的問題。Eureka 采用的就是P2P復制模式,我們從客戶端和服務端兩個角度來闡述。
? ? ? ? 3.2.1? 客戶端
? ? ? ? 客戶端使用quarantineSet維護了一個不可用的Eureka Server列表,進行重試的時候,會優先從可用的列表中進行選擇,如果請求失敗則切換到下一個Eureka Server進行重試,默認重試次數是3次。
? ? ? ? 另外為了防止每個Client端都按配置文件指定的順序進行請求造成Eureka Server節點請求不均衡,Client端有個定時任務(默認5分鐘一次)來刷新并隨機化Eureka Server可用列表。
? ? ? ? 3.2.2? 服務端
? ? ? ? 當集群中的單個Eureka Server啟動的時候,會有一個syncUp的操作,通過Eureka Client請求其他Eureka Server節點中的一個節點來獲取注冊的應用實例信息,然后復制到其它Peer節點。
? ? ? ? Eureka Server在進行復制操作的時候,使用HEADER_REPLICATION的http_header來將整個請求操作與普通應用實例的正常請求操作區分開來。通過HEADER_REPLICATION 來標識是復制請求,這樣其它節點接收到請求的時候,就不會再對它的Peer節點進行復制操作,從而避免死循環。
? ? ? ? 由于采用了P2P復制模式,其重點要解決的另外一個問題就是數據復制沖突的問題。這蒙迪歐這幾個問頭,Eureka采用兩個方式來解決:lastDirtyTimestamp標識 和 heartbeat
? ? ? ? 首先Eureka Server默認開啟了SyncWhenTimestampDiffers配置,如果請求參數的lastDirtyTimestamp 值 大于 Server本地實例的lastDirtyTimestamp值,那就標識Eureka Server之間的數據有沖突,返回404,要求應用實例重新進行register操作。如果請求參數的?lastDirtyTimestamp 值 小于?Server本地實例的?lastDirtyTimestamp值, 如果是peer節點的復制請求,則表示數據出現沖突,返回409給peer節點,要求其同步自己最新的數據信息。
? ? ? ? 其次peer節點之間的相互復制也不能保證所有操作都能成功,因此Eureka還通過應用實例與Server之間的heartbeat也就是renewLease操作來進行數據的最終修復,即如果發現應用實例數據與某個Server的數據出現不一致,則Server返回404,告知應用實例重新進行register操作。
? ? ? ? 3.2.3? SELF PRESERVATION
? ? ? ? 在分布式系統設計中,通常需要對應用實例的存活進行檢查,這里比較關鍵的問題就是要處理好網絡偶爾抖動或短暫不可用時造成的誤判。另外Eureka Server端與Client端之間如果出現網絡區分問題,在極端情況下可能會使得Eureka Server清空部分服務的實例列表,造成不可用性。所以Eureka引入了SELF PRESERVATION。
? ? ? ? Eureka的Client端與Server端有個租約,Client端要定時發送心跳到Server端,來維持這個租約,告知Server端自己仍然健康的活著。Eureka通過當前注冊的實例數,去計算每分鐘應該從應用實例接收到的心跳數,如果最近一分鐘接收到的續約的次數小于等于指定閾值的話,則關閉租約失效剔除,進制定時任務刪除失效的實例,從而保護注冊信息。