微服務(組件篇)[Eureka]

Eureka 原理

Eureka 的服務註冊機制

服務註冊機制

  • 新的服務部署完成後,會訪問 Eureka Server,來給自己註冊。
  • 每個 Eureka Client,每隔 30 秒,會從 Eureka Server 獲取註冊表的變化,以便及時得知哪些服務已經掛了。
  • 每個 Eureka Client,每隔 30 秒,會發送心跳給 Eureka Server,證明自己還活着。

Eureka Server 的訪問頻率

假設現在有 100 個服務,每個服務部署到 20 臺服務器上,機器是標準的 4 核 8G 配置。相當於 100 * 20 = 2000 個服務,也就是 2000 臺服務器。每臺服務器上都有一個 Eureka Client 組件,他們每隔 30 秒都會訪問 2 次 Eureka Server,一次是獲取註冊表的變化,一次是發送心跳。

  • 每分鐘:一臺服務器獲取 2 次註冊表的變化,發送 2 次心跳,2000 臺服務器,Eureka Server 就要被訪問 8000 次。
  • 每秒:8000 / 60 ≈ 133 次,算上其它一些額外操作,我們算作 200 次左右。
  • 每天:8000 * 60 * 24 = 1152 萬次。

對於上述情況,Eureka Server 將要面對日千萬級的訪問量。

Eureka Server 的存儲方式

首先,我們來看看 Eureka 存儲註冊表的源碼。

public abstract class AbstractInstanceRegistry implements InstanceRegistry {
	private final ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>> registry = new ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>();
}
  • registry:以 ConcurrentHashMap 作爲核心結構,說明註冊表是基於純內存的。key
    是服務名稱,如:user-service。value 是服務的多個實例。
  • Map<String, Lease<InstanceInfo>>:key 是服務實例的 id,InstanceInfo
    存儲服務實例的具體信息,如 IP 地址、端口、hostname 等。
  • Lease:維護服務實例的最近心跳時間。

結論:維護註冊表、獲取註冊表的變化、更新心跳時間的操作,全部都發生在內存裏,速度快也就不難理解了。

Eureka 的多級緩存機制

多級緩存儘可能保證註冊表的數據不會頻繁的出現讀寫衝突問題。也提高了速度,性能很高。
多級緩存

  • 當 Eureka Client 獲取註冊表時,先讀取 ReadOnlyCacheMap,如果沒有,就去讀 ReadWriteCacheMap,還沒有,就直接讀取註冊表。
  • 當註冊表發生變化時,會過期掉 ReadWriteCacheMap,不影響讀取 ReadOnlyCacheMap(30 秒內)。
  • 30 秒後,Eureka Server 發現 ReadWriteCacheMap 已經被清空了,就會清空 ReadOnlyCacheMap。
  • Eureka Client 再次獲取註冊表時,發現兩個 CacheMap 都是空的,就會直接讀取註冊表,同時填充緩存。

Eureka 的特點總結

  • 請求頻率:每 30 秒獲取一次註冊表,每 30 秒發送一次心跳。保證了每秒處理幾百次請求的能力。
  • 純內存註冊表:所有請求都可以在內存中處理。保證了高性能。
  • 多級緩存機制:避免發生頻繁的讀寫衝突,進一步提升性能。

Eureka 與 Zookeeper

相同點

Eureka 和 Zookeeper 都在分佈式系統中,充當着服務註冊中心的角色。
作爲服務管理組件,都需要具備以下三個能力:

  • 熔斷:當檢測到某個服務異常時,要及時把它斷掉,以防整個項目被拖垮。
  • 降級:在業務高峯期,爲了保障核心服務,把不重要的服務暫時停掉。
  • 限流:面對突然的大量請求,爲了保障服務節點的正常運行,要每隔一段時間,再放一批請求進去。

不同點

Zookeeper 作爲第三方組件,被 Dubbo 使用;而 Eureka,是 Spring Cloud 中的自帶組件。
說到這兒,我們有必要看看 Dubbo 與 Spring Cloud 的區別:

  • 服務調用方式:Dubbo 是基於 RPC 調用的;Spring Cloud 是基於 HTTP 協議的 REST API
    調用的。所以在遠程調用的效率上,Dubbo 大約是 Spring Cloud 的三倍。
  • 框架:Dubbo 是一個微服務治理的框架,依賴於很多第三方插件;而 Spring Cloud 有一套成熟的解決方案。

Zookeeper 放棄了一定的可用性,在服務器掛了後,需要選舉出新的 leader,會產生延遲;而 Eureka 爲了保證可用性,設定每個節點都是公平的,不需要選舉 leader,但也放棄了一致性。

栗子

爲了測試分佈式,我們先配置 host,模擬服務端和客戶端。
127.0.0.1 master
127.0.0.1 slave
127.0.0.1 slave2

創建 Eureka 服務項目(eurekaserver)

  • 第一步:選擇 Create New Project,創建一個 Spring Initializr 項目,選擇 Web 組件和 Eureka Server 組件。
    創建項目
    起名
    Web
    Eureka Server
  • 第二步:在啓動類中加入 Eureka 的服務註解 @EnableEurekaServer。
    @EnableEurekaServer
  • 第三步:配置服務屬性。
    配置
  • 第四步:啓動項目,訪問 127.0.0.1:8761,進入管理界面。
    服務
    可以看到 EUREKASERVER 服務已經註冊進去了。

創建 Eureka 服務提供項目(user)

  • 第一步:選擇 Create New Project,創建一個 Spring Initializr 項目,選擇 Web 組件和 Eureka Discovery 組件。
    Eureka Discovery
  • 第二步:在啓動類中加入 Eureka 的客戶端註解 @EnableEurekaClient。
    @EnableEurekaClient
  • 第三步:配置客戶端屬性。
    配置
  • 第四步:編寫測試接口。
    測試接口
    第五步:啓動項目,訪問 127.0.0.1:8761,進入管理界面。
    服務
    可以看到 USER 服務也註冊進去了。

創建 Eureka 服務調用項目(customer)

  • 第一步:選擇 Create New Project,創建一個 Spring Initializr 項目,選擇 Web 組件和 Eureka Discovery 組件。
  • 第二步:在啓動類中加入 Eureka 的客戶端註解 @EnableEurekaClient。
  • 第三步:配置客戶端屬性。
    配置
  • 第四步:調用服務端的接口。
    測試接口
  • 第五步:啓動項目,訪問 127.0.0.1:8080/test/testByEureka。
    結果
    我們可以看到 customer 成功的訪問到了 user 服務。使用 HTTPclient 的方式訪問接口,有點麻煩,我們可以使用 Eureka 中的 RestTemplate,不僅方便,還支持負載均衡。
    RestTemplate
    再啓動一個相同的 user,把端口改爲 8200,訪問 127.0.0.1:8761,進入管理界面。
    服務
    可以看到現在有2個 USER 服務,端口分別爲 8100 和 8200。
    訪問 127.0.0.1:8080/test/testByRestTemplate。
    第一次調用了 8200 服務。
    結果
    刷新時,調用了 8100 服務。
    在這裏插入圖片描述
    再次刷新,又調用了 8200 服務。(默認分配算法是輪詢)
    結果
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章