本文是Spring Cloud專欄的第三篇文章,了解前兩篇文章內容有助於更好的理解后面文章:
一、Eureka注冊中心高可用集群概述
在微服務架構的這種分布式系統中,我們要充分考慮各個微服務組件的高可用性問題,不能有單點故障,由於注冊中心Eureka本身也是一個服務,如果它只有一個節點,那么它有可能發生故障,這樣我們就不能注冊與查詢服務了,所以我們需要—個高可用的服務注冊中心,這就需要通過注冊中心集群來解決。Eureka服務注冊中心它本身也是一個服務,它也可以看做是一個提供者,又可以看做是一個消費者,我們之前通過配置eureka.client.register-with-eureka= false讓注冊中心不注冊自己,但是我們可以向其他注冊中心注冊自己。
Eureka server的高可用實際上就是將自己作為服務向其他服務注冊中心注冊自己,這樣就會形成一組互相注冊的服務注冊中心,進而實現服務清單的互相同步,往注冊中心A上注冊的服務,可以被復制同步到注冊中心B上,所以從任何一台注冊中心上都能查詢到已經注冊的服務,從而達到高可用的效果。
二、Eureka注冊中心高可用集群搭建
Eureka注冊中心高可用集群就是各個注冊中心相互注冊
1、我們復制Eureka服務端(springcloud-eureka-server)的application.yml為application-eureka8701.yml,application-eureka8702.yml,我們讓8701和8702的Eureka服務相互注冊。
修改application-eureka8701.yml相應的配置如下:
2、復制SpringcloudEurekaServerApplication啟動類命名為SpringcloudEureka8701ServerApplication,SpringcloudEureka8702ServerApplication,鼠標放在啟動類上右鍵選擇如圖
然在啟動類SpringcloudEureka8701ServerApplication添加-Dspring.profiles.active=eureka8701
同理8702啟動類操作也是一樣,此處省略。
3、為了讓eureka8701和eureka8702能夠被正確相互訪問到,同步數據,如果不能相互訪問,Eureka服務中的數據不能同步共享,我們需要在C:\Windows\System32\drivers\etc目錄下的hosts文件中添加兩行配置,如下:
127.0.0.1 eureka8701
127.0.0.1 eureka8702
4、啟動兩個SpringcloudEureka8701ServerApplication,SpringcloudEureka8702ServerApplication服務我們可以看到注冊成功了。
Eureka8702也是如此,到此Eureka服務集群搭建完畢
三、Eureka詳解
1、服務消費者模式
1-1、獲取服務
消費者啟動的時候,使用服務別名,會發送一個rest請求到服務注冊中心獲取對應的服務信息,然后會緩存到本地jvm客戶端中,同時客戶端每隔30秒從服務器上更新一次。
可以通過eureka.client.registry-fetch-interval-seconds=30參數進行修改,該配置默認值為30, 單位為秒。
1-2、服務下線
在系統運行過程中必然會面臨關閉或重啟服務的某個實例的情況,在服務關閉期間我們自然不希望客戶端會繼續調用關閉了的實例。所以在客戶端程序中,當服務實例正常的關閉操作時,它會觸發一個服務下線的REST請求給Eureka Server, 告訴服務中心:“我要下線了”。服務端在接收到請求之后,將該服務狀態置為下線(DOWN),並將該下線事件傳播出去。
2、服務注冊模式
2-1、失效剔除
有些時候,我們的服務實例並不一定會正常下線,可能由於內存溢出、網絡故障原因使得服務不能正常工作,而服務注冊中心並未收到“服務下線”的請求。為了從服務表中將這些無法提供服務的實例剔除,Eureka Server 在啟動的時候會創建一個定時任務默認每隔一段時間(默認為60秒eureka.server.eviction-interval-timer-in-ms=6000L)將當前清單中超時(默認為90秒eureka.instance.lease-expiration-duration-in-seconds= 90)沒有續約的服務踢除出去
2-2、Eureka服務注冊中心自我保護機制
當我們在本地調試基於Eureka的程序時,基本上都會碰到這樣一個問題, 在服務主中心的信息面板中出現類似下面的紅色警告信息,在開發測試時,需要頻繁地重啟微服務實例,但是我們很少會把eureka server一起重啟(因為在開發過程中不會修改eureka注冊中心),當一分鍾內收到的心跳數大量減少時,會觸發該保護機制。可以在eureka管理界面看到Renews threshold和Renews(last min),當后者(最后一分鍾收到的心跳數)小於前者(心跳閾值)的時候,觸發保護機制,會出現紅色的警告:
實際上,該警告就是觸發了Eureka Server的自我保護機制,服務注冊到Eureka Server之后,會維護個心跳連接, 告訴Eureka Server自己還活着。Eureka Server在運行期間,會統計客戶端節點的心跳失敗的比例在15分鍾之內是否低於85%如果出現低於的情況,如果低於85%,那就觸發自我保護機制,單機調試的時候很容易滿足,實際在生產環境上通常是由於網絡不穩定導致),Eureka Server會將當前的實例注冊信息保護起來,讓這些實例不會過期,盡可能保護這些注冊信息。但是,在這段保護期間內實例若出現問題,那么客戶端很容易拿到實際已經不存服務實例,會出現調用失敗的情況,所以客戶端必須要有容錯機制,比如可以使用請使用重試、斷路器等機制。
在沒有Eureka自我保護的情況下,如果 Eureka Server在一定時間內沒有接收到某個微服務實例的心跳, Eureka Server將會注銷該實例,但是當發生網絡分區故障時,那么微服務與 Eureka Server之間將無法正常通信,以上行為可能變非常危險了,因為微服務本身其實是正常的,此時不應該注銷這個微服務,如果沒有自我保護機制,那么Eureka Server就會將此服務注銷掉。
Eureka通過“自我保護模式”來解決這個問題——當 Eureka Server節點在短時間內丟失過多客戶端時(可能發生了網絡分區故障),那么就會把這個微服務節點進行保護。一旦進入自我保護模式, Eureka server就會保護服務注冊表中的信息,不刪除服務注冊表中的數據(也就是不會注銷任何微服務)。當網絡故障恢復后,該 Eureka Server節點會再自動退出自我保護模式。所以,自我保護模式是一種應對網絡異常的安全保護措施,它的架構哲學是寧可同時保留所有微服務(健康的微服務和不健康的微服務都會保留),也不盲目注銷任何健康的微服務,使用自我保護模式,可以讓Eureka集群更加的健壯、穩定當然也可以使用配置項: eureka.server.enable-self-preservation=fase禁用自我保護模式。
但是Eureka Server自我保護模式也會給我們帶來一些困擾,如果在保護期內某個服務提供者剛好非正常下線了,此時服務消費者就會拿到一個無效的服務實例,此時會調用失敗,對於這個問題需要服務消費者端具有一些容錯機制,如重試,斷路器等。
Eureka的自我保護模式是有意義的,該模式被激活后,它不會從注冊列表中剔除因長時間沒收到心跳導致注冊過期的服務,而是等待修復,直到心跳恢復正常之后,它自動退出自我保護模式。這種模式旨在避免因網絡分區故障導致服務不可用的問題。
例如,兩個微服務客戶端實例A和B之間有調用的關系,A是消費者,B是提供者,但是由於網絡故障,B未能及時向Eureka發送心跳續約,這時候 Eureka不能簡單的將B從注冊表中剔除,因為如果剔除了,A就無法從Eureka服務器中獲取B注冊的服務,但是這時候B服務是可用的;所以, Eureka的自我保護模式最好還是開啟它。
2-3、關閉自我保護的相關配置如下
-
服務端配置
-
客戶端配置
-
關閉自我保護模式Eureka服務端顯示如下:
案例源碼地址:https://gitee.com/coding-farmer/springcloud-learn