Spring Cloud Eureka 詳解

一、Spring Cloud Eureka簡介       

       Spring Cloud Eureka,使用Netflix Eureka 來實現服務的註冊與發現, 他既包含了服務端組件,也包含了客戶端組件,並且服務端與客戶端均採用Java編寫,所以Eureka主要適用於通過Java編寫的分佈式系統,或是與JVM兼容語言構建的系統。但是,由於Eureka的服務端的服務治理機制提供了完備的Restful API,所以它也支持將非Java語言構建的微服務應用納入Eureka的服務治理體系中來。只是在使用其他語言平臺的時候,需要自己來實現Eureka的客戶端程序。不過慶幸的是,在目前幾個較爲流行的開發平臺上,都已經有了一些針對Eureka註冊中心的客戶端實現框架,比如.NET平臺的Steeltoe,Node.js的eureka-js-client等。

       Eureka服務端,我們也稱爲服務註冊中心,它同其他服務註冊中心一樣,支持高可用配置。它依託於強一致性提供良好的服務實例可用性,可以應對多種不同的故障場景。如果Eureka以集羣模式部署,當集羣中有分片出現故障時,那麼Eureka就轉入自我保護模式。它允許在分片故障的期間繼續提供服務的發現和註冊,當故障分片恢復運行時集羣中的其他分片會把它們的狀態再次同步回來。以AWS上的實踐爲例,Netflix推薦每個可用的區域運行一個Eureka服務端,通過它來形成集羣。不同可用區域的服務註冊中心通過異步模式互相複製各自的狀態,這意味着在任意給定的時間點每個實例關於所有服務的狀態是有細微差別的。

       Eureka客服端,主要處理服務的註冊與發現。客戶端服務通過註解和參數配置的方式,嵌入在客戶端應用程序的代碼中,在應用程序運行時,Eureka客戶端向註冊中心註冊自身提供的服務並定期性的發送心跳來更新它的服務租約。同時,它也能從服務端查詢當前註冊的服務信息並把它們緩存到本地並週期性的刷新服務狀態。

二、Eureka服務治理體系

      Eureka服務治理體系三個核心角色:服務註冊中心、服務提供者以及服務消費者。

基礎架構

  • 服務註冊中心:Eureka提供的服務端,提供服務註冊與發現的功能。
  • 服務提供者:提供服務的應用,可以是SpringBoot應用,也可以是其他技術平臺且遵循Eureka通信機制的應用。它將自己提供的服務註冊到Eureka,以供其他應用發現。
  • 服務消費者:消費者應用從服務註冊中心獲取服務列表,從而使消費者知道可以從何處調用其所需要的服務。

    很多時候客戶端即使服務提供者也是服務消費者,服務註冊中心就是不同服務之間相互調用的紐帶。

服務治理機制

    我們將通過下圖,來展示Eureka服務治理體系是如何運行起來的。

Eureka服務治理體系
  • ”服務註冊中心-1“和“服務註冊中心-2”,它們相互註冊成了高可用集羣。
  • “服務提供者”啓動了兩個實例,一個註冊到“服務註冊中心-1”上,另外一個註冊到“服務註冊中心-2”上。
  • 還要兩個“服務消費者”,它們分別指向了一個註冊中心。

   根據上面的結構,下面我們來詳細瞭解一下,從服務註冊開始到服務調用,及各個元素所涉及的一些重要通信行爲。

   服務提供者

   服務註冊

   “服務提供者”在啓動的時候會通過發送REST請求的方式將自己註冊到Eureka Server上,同時帶上了自身服務的一些元數據信息。Eureka Server接收到這個REST請求之後,將元數據存儲在一個雙層結構Map中,其中第一層的key是服務名,第二層的key是具體服務的實例名。

   在服務註冊時,需要確認一下 eureka.client.register-with-eureka=true參數是否正確,該值默認爲true。若設置爲false將不會啓動註冊操作。

   服務同步

   如圖架構所示,這裏的兩個服務提供者分別註冊到了兩個不同的服務註冊中心上,也就是說,它們的信息分別被兩個服務註冊中心所維護。此時,由於服務註冊中心之間因爲相互註冊爲服務,當服務提供者發送註冊請求到一個服務註冊中心時,它會將該請求轉發給集羣中相連的其他註冊中心,從而實現註冊中心之間的服務同步,通過服務同步,兩個服務提供者的服務信息就可以通過這兩臺服務註冊中心中的任意一臺獲取到。

   服務續約

   在註冊完服務之後,服務提供者會維護一個心跳用來持續告訴Eureka Server:“我還活着”,以防止Eureka Server 的“剔除任務”將該服務實例從服務列表中排除出去,我們稱該操作爲服務續約(Renew)。

   關於服務續約的兩個重要屬性,我們可以關注並根據需要來進行調整。

   eureka.instance.lease-renewal-interval-in-seconds=30

   eureka.instance.lease-expiration-duration-in-seconds=90

  eureka.instance.lease-renewal-interval-in-seconds參數用於定義服務續約任務調用間隔時間,默認爲30秒。eureka.instance.lease-expiration-duration-in-seconds參數用於定義服務失效的時間,默認爲90秒。

    服務消費者

    獲取服務

    到這裏,在服務註冊中心已經註冊了一個服務,並且該服務有兩個實例。當我們啓動服務消費者時,它會發送一個REST請求給服務註冊中心,來獲取上面註冊的服務清單。爲了性能考慮,Eureka Server 會維護一份只讀的服務清單來返回給客戶端,同時該緩存清單會每隔30秒更新一次。

  獲取服務是服務消費者的基礎,所以要確保 eureka-client-fetch-registery=true 參數沒有被修改成false,該值默認爲 true。若想修改緩存清單的更新時間,可以通過 eureka-client.registry-fetch-interval-seconds=30 參數來進行修改,該值默認爲30,單位爲秒。

    服務調用

    服務消費者在獲取服務清單後,通過服務名可以獲得具體提供服務的實例名和該實例的元數據信息。因爲有這些服務實例的詳細信息,所以客戶端可以根據自己的需要決定具體需要調用的實例,在Ribbon中會默認採用輪詢的方式進行調用,從而實現客戶端的負載均衡。

    對於訪問實例的選擇,Eureka中有Region和Zone的概念,一個Region中可以包含多個Zone,每個服務客戶端需要被註冊到一個Zone中,所以每個客戶端對應一個Region和一個Zone。在進行服務調用的時候,優先訪問同處一個Zone中的服務提供方,若訪問不到,就訪問其他Zone。

    服務下線

    在系統運行過程中必然會面臨關閉或重啓服務的某個實例的情況,在服務關閉期間,我們自然不希望客戶端會繼續調用關閉了的實例。所以在客戶端程序中,當服務實例進行正常的關閉操作時,它會觸發一個服務下線的REST請求給 Eureka Server,告訴服務註冊中心:“我要下線了”。服務端在接收到請求之後,將該服務狀態設置爲下線(DOWN),並把該下線事件傳播出去。

    服務註冊中心

    失效剔除

    有些時候,我們的服務實例並不一定會正常下線,可能由於內存溢出、網絡故障等原因使得服務不能正常工作,而服務註冊中心並未收到“服務下線”的請求。爲了從服務列表中將這些無法提供服務的實例剔除,Eureka Server在啓動的時候會創建一個定時任務,默認每隔一段時間(默認爲60秒)將當前清單中超時(默認爲90秒)抹油續約的服務剔除出去。

    自我保護

    當我們在本地調試基於Eureka的程序時,基本上都會碰到這樣的一個問題,在服務註冊中心的信息面板中出現類似下面的紅色警告信息:

 

     實際上,該警告就是觸發了Eureka Server的自我保護機制。之前介紹過,服務註冊到Eureka Server之後,會維護一個心跳連接,告訴Eureka Server 自己還活着。Eureka Server 在運行期間,會統計心跳失敗的比例在15分鐘之內低於85%,如果出現低於的情況,Eureka Server 會將當前的實例信息保護起來,讓這些實例不會過期,儘可能保護這些註冊信息。但是,在保護期間內實例若出現問題,那麼客戶端很容易拿到實際已經不存在的服務實例,會出現調用失敗的情況,所以客戶端必須要有容錯機制,比如可以使用請求重試、斷路器等機制。

  由於在本地調試很容易觸發註冊中心的保護機制,使得註冊中心維護的服務實例不那麼準確。可以在本地進行開發時,使用 eureka-server.enable-self-preservation=false 參數來關閉保護機制,確保註冊中心將不可用的實例正確剔除。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章