4、Spring Cloud Eureka詳解

一、基礎架構
在上一節當中,我們通過一個簡單的服務註冊與發現示例,構建了Eureka服務治理體系中的三個核心角色:服務註冊中心、服務提供者、服務消費者。通過以上章節,相信我們已經對Eureka的服務治理有了一些初步的認識。
至此,我們已經學會了如何構建服務註冊中心(包括單節點和高可用部署),也知道了如何構建Eureka的服務提供者和消費者。但是,在實際開發中這些是遠遠不夠的。在此,我們將更深次的學習Eureka的基礎架構、節點間的通信和一些進階配置!

在上述示例中,我們講的示例雖然簡單,但是包含了整個Eureka服務治理基礎架構的三個核心要素。
  • 服務註冊中心:Eureka提供的服務端,提供服務的註冊與發現功能,也就是我們的eureka-server
  • 服務提供者:提供服務的應用。他將自己提供的服務註冊到Eureka註冊中心裏,以供其他應用發現、使用,也就是我們的eureka-service-hello
  • 服務消費者:消費者從註冊中心獲取服務列表,從而使消費者知道在何處調用其所需要的服務,上述中使用了Ribbon來實現消費服務,後續會介紹Feign的消費方式

二、服務提供者
服務提供者在啓動的時候會通過發送REST請求的方式將自己註冊到Eureka Server上,同時帶上了自身服務的一些元數據信息。Eureka Server將元數據信息存儲在一個雙層Map中,其中第一層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-registry=true 參數沒有被修改成false。
若希望修改緩存清單的更新時間,可以通過:
eureka.client.registry-fetch-interval-seconds=30
該參數默認值爲30,單位爲秒!

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

四、服務註冊中心
失效剔除:有些時候,我們服務實例並不一定會正常下線,可以一些特殊原因而不能正常工作(內存溢出、網絡故障),而註冊中心並未收到“服務下線”的請求。爲了從服務列表中將這些無法提供服務的實例剔除,Eureka Server在啓動的時候會創建一個定時任務,默認每隔一段時間(默認時間60秒)將默認清單中超時(默認時間90秒--eureka.instance.lease-expiration-duration-in-seconds 定義的時間)沒有續約的服務剔除出去。
自我保護:在我們本地調試基於Eureka 程序時,基本上都會碰到這樣一個問題,在服務註冊中心的信息面板中會出現類似下面的紅色警告信息:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

實際上,這種警告就是觸發了Eureka Server的自我保護機制。如果Eureka Server在一定時間內(默認90秒)沒有接收到某個微服務實例的心跳,Eureka Server將會移除該實例。但是當網絡分區故障發生時,微服務與Eureka Server之間無法正常通信,而微服務本身是正常運行的,此時不應該移除這個微服務,所以引入了自我保護機制。
自我保護機制的工作機制是如果在15分鐘內超過85%的客戶端節點都沒有正常的心跳,那麼Eureka就認爲客戶端與註冊中心出現了網絡故障,Eureka Server自動進入自我保護機制,此時會出現以下幾種情況:
1、Eureka Server不再從註冊列表中移除因爲長時間沒收到心跳而應該過期的服務。
2、Eureka Server仍然能夠接受新服務的註冊和查詢請求,但是不會被同步到其它節點上,保證當前節點依然可用。
3、當網絡穩定時,當前Eureka Server新的註冊信息會被同步到其它節點中。
因此Eureka Server可以很好的應對因網絡故障導致部分節點失聯的情況,而不會像ZK那樣如果有一半不可用的情況會導致整個集羣不可用而變成癱瘓。
自我保護開關
Eureka自我保護機制,通過配置 eureka.server.enable-self-preservation來true打開/false禁用自我保護機制,默認打開狀態,建議生產環境打開此配置。

五:配置Region和Zone

Region和Zone就相當於大區和機房,一個Region(大區)可以有很多的Zone(機房)。在Spring Cloud中,服務消費者會優先查找在同一個Zone的服務,之後在去查找其他的服務。如果該項配置使用的好,那麼項目請求的響應時間將大大縮短!

六、註冊中心的安全機制
爲了註冊中心的安全考慮,很多時候我們都會爲註冊中心加入安全校驗!
服務端
1、Eureka Server pom.xml 中加入依賴
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.在application.properties加入認證的用戶名和密
security.user.name=你的用戶名
security.user.password=你的密碼
3.在訪問路徑上加入用戶名密碼
eureka.client.serviceUrl.defaultZone=http://${security.user.name}:${security.user.password}@127.0.0.1:${server.port}/eureka/

client端
這個時候,在配置service-url時,需要在value值的URL中加入相應的安全檢驗信息,比如 http://<username>:<password>@localhost:8080/eureka/。其中 <username>爲安全檢驗名,<password>爲該用戶的密碼!

七、Eureka 注意要點解釋
以下摘抄於:http://fengyilin.iteye.com/blog/2367265 fengyilin 的博客,如有侵權,請聯繫我刪除!
基礎架構:
1.Eureka 包含server和client兩個基本組件,以下摘自Netflix的描述
引用
Eureka 是一種基於REST服務,主要用在AWS雲中,用來提供負載均衡和中間層服務的故障轉移,我們把這種REST服務稱作Eureka server。Eureka 還包含一個基於Java的客戶端,可以用來更好的server交互,Eureka client包含一個內建的基於round-robin(輪詢)的負載均衡策略。

2.每一個Eureka client應用被稱作一個instance。Eureka client應用和Eureka client也有着細微的差別,前者指的是我們自己的應用程序,後者代表的是框架提供的一個組件。(在maven工程中,自己的應用程序需要依賴Eureka client相關的jar)
3.Eureka 具有很靈活的動態配置特性。既有用來設置初始配置的屬性,也有用來週期性的檢查這些配置是否有變化的配置。其中的大多數配置都可以在運行時修改,並在下一個刷新週期中起作用。例如:Eureka client用來註冊到Eureka server的URL可以動態改變,並在5分鐘後被識別(eureka.client.eurekaServiceUrlPollIntervalSeconds配置)。所有的配置屬性如下:
Eureka server:
Eureka client:
Eureka instance:
org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean,此類間接實現了com.netflix.appinfo.EurekaInstanceConfig,所有的配置屬性以eureka.instance開頭。

二、Eureka Instance 和Eureka client主要配置
1、在Eureka中,一個 instance 通過一個 eureka.instance.instanceId 來唯一標識,如果這個值沒有設置,就採用eureka.instance.metadataMap.instanceId代替。instance 之間通過 eureka.instance.appName 來彼此訪問,在spring cloud中默認值是 spring.application.name ,如果沒有設置則爲 UNKNOWN。在實際使用中 spring.application.name 不可或缺,因爲相同名字的應用會被Eureka合併成一個羣集(Eureka Server會以雙層Map進行存儲信息,第一層Map的key 就是服務名, 第二層 Map的 key 就是 instanceId)。eureka.instance.instanceId 也可以不設置,直接使用缺省值(client.hostname:application.name:port)
,同一個appName下InstanceId不能相同。屬性eureka.instance.virtualHostName目前在spring cloud中目前沒有用,默認值是appName或者UNKNOWN。

2、如果 eureka.client.registerWithEureka 設置成true(默認值true),應用啓動時,會利用指定的eureka.client.serviceUrl.defaultZone(也可以自定義Zone) 註冊到對應的Eureka server中。之後每隔30s(通過eureka.instance.leaseRenewalIntervalInSeconds來配置)向Eureka server發送一次心跳,如果Eureka server在90s(通過eureka.instance.leaseExpirationDurationInSeconds配置)內沒有收到某個instance發來的心跳就會把這個instance從註冊中心中移走。發送心跳的操作是一個異步任務,如果發送失敗,則以2的指數形式延長重試的時間,直到達到eureka.instance.leaseRenewalIntervalInSeconds * eureka.client.heartbeatExecutorExponentialBackOffBound這個上限,之後一直以這個上限值作爲重試間隔,直至重新連接到Eureka server,並且重新嘗試連接到Eureka server的次數是不受限制的。

3、在Eureka server中每一個instance都由一個包含大量這個 instance 信息的com.netflix.appinfo.InstanceInfo標識,client向Eureka server 發送心跳和更新註冊信息是不相同的,InstanceInfo 也以固定的頻率發送到Eureka server,這些信息在Eureka client啓動後的40s(通過 eureka.client.initialInstanceInfoReplicationIntervalSeconds 配置)首次發送,之後每隔30s(通過eureka.client.instanceInfoReplicationIntervalSeconds配置)發送一次。

4、如果 eureka.client.fetchRegistry 設置成true(默認值true),Eureka client在啓動時會從Eureka server獲取註冊信息並緩存到本地,之後只會增量獲取信息(可以把 eureka.client.shouldDisableDelta 設置成false來強制每次都全量獲取)。獲取註冊信息的操作也是一個異步任務,每隔30秒執行一次(通過 eureka.client.registryFetchIntervalSeconds 配置),如果操作失敗,也是以2的指數形式延長重試時間,直到達到
eureka.client.registryFetchIntervalSeconds * eureka.client.cacheRefreshExecutorExponentialBackOffBound 這個上限,之後一直以這個上限值作爲重試間隔,直至重新獲取到註冊信息,並且重新嘗試獲取註冊信息的次數是不受限制的。
這些任務都是在com.netflix.discovery.DiscoveryClient中啓動,spring cloud用org.springframework.cloud.netflix.eureka.CloudEurekaClient對這個類進行了擴展。
更詳盡的知識請參考:http://fengyilin.iteye.com/blog/2367265 




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