Spring Cloud Netflix 是什么
This project provides Netflix OSS integrations for Spring Boot apps through autoconfiguration and binding to the Spring Environment and other Spring programming model idioms. With a few simple annotations you can quickly enable and configure the common patterns inside your application and build large distributed systems with battle-tested Netflix components. The patterns provided include Service Discovery (Eureka), Circuit Breaker (Hystrix), Intelligent Routing (Zuul) and Client Side Load Balancing (Ribbon).
Spring Cloud Netflix 基於 Spring Boot,集成了NetFlix OSS的一些組件,只需通過注解配置和Spring的簡單注解,就可以快速的啟用和配置NetFlix的組件實現分布式系統的構建。這些組件包含的功能有服務發現(Eureka),熔斷器(Hystrix),智能路由(Zuul)以及客戶端的負載均衡器(Ribbon)
Spring Cloud Eureka 是什么
Spring Cloud Eureka 是基於Spring Cloud Netflix 做了二次封裝,它主要負責完成各個微服務實例的自動化注冊和發現功能。
Spring Cloud Eureka 相關概念
服務提供者
1.服務注冊
When a client registers with Eureka, it provides meta-data about itself such as host and port, health indicator URL, home page etc. Eureka receives heartbeat messages from each instance belonging to a service. If the heartbeat fails over a configurable timetable, the instance is normally removed from the registry.
服務在啟動的時候會通過發送REST請求的方式將自己注冊到Eureka Server上, 同時帶上了自身服務的一些元數據信息。注冊中心Eureka Server通過與服務之間的心跳來保持通信,當某個服務實例在超時時間內沒有與注冊中心保持會話,那么該服務實例將會從注冊中心正常移除。
Eureka Server 接收到這個REST請求之后,將元數據信息存儲在一個雙層結構Map中, 其中第一層的key是服務名, 第二層的key是具體服務的實例名。
2.服務同步
如架構圖中所示,這里的兩個服務提供者分別注冊到了兩個不同的服務注冊中心上,它們的信息分別被兩個服務注冊中心所維護。由於服務注冊中心之間因互相注冊為服務, 當服務提供者發送注冊請求到一個服務注冊中心時, 它會將該請求轉發給集群中相連的其他注冊中心, 從而實現注冊中心之間的服務同步。通過服務同步,兩個服務提供者的服務信息就可以通過這兩台服務注冊中心中的任意一台獲取到。
3.服務續約
在注冊完服務之后,服務提供者會維護一個心跳用來保持與EurekaServer 的會話,以防止Eureka Server 的剔除任務將該服務實例從服務列表中移除掉,那么這個心跳保持就叫做服務續約(Renew)。
關於服務續約有兩個重要屬性,我們可以關注並根據需要來進行調整:
服務續約任務的調用間隔時間,默認為30秒
eureka.instance.lease-renewal-interval-in-seconds=30
服務失效的時間,默認為90秒。
eureka.instance.lease-expiration-duration-in-seconds=90
服務消費者
1.獲取服務
當啟動服務消費者的時候,它會發送一個REST請求給服務注冊中心,來獲取上面注冊的服務列表。Eureka Server會維護一份只讀的服務列表來返回給客戶端,同時服務消費者會在本地緩存服務列表的清單並每隔30秒更新一次。
獲取服務是服務消費者的基礎,所以必有兩個重要參數需要注意:
# 啟用服務消費者從注冊中心拉取服務列表的功能
eureka.client.fetch-registry=true
# 設置服務消費者從注冊中心拉取服務列表的間隔
eureka.client.registry-fetch-interval-seconds=30
2.服務調用
服務消費者在獲取服務清單后,通過服務名可以獲得具體提供服務的實例名和該實例的元數據信息。因為有這些服務實例的詳細信息, 所以客戶端可以根據自己的需要決定具體調用哪個實例,在ribbon中會默認采用輪詢的方式進行調用,從而實現客戶端的負載均衡。
對於訪問實例的選擇,Eureka中有Region和Zone的概念, 一個Region中可以包含多個Zone, 每個服務客戶端需要被注冊到一個Zone中, 所以每個客戶端對應一個Region和一個Zone。在進行服務調用的時候,優先訪問同處一個Zone 中的服務提供方,若訪問不到,就訪問其他的Zone。
3.服務下線
在客戶端程序中,當服務實例進行正常的關閉操作時,它會觸發一個服務下線的REST請求給Eureka Server, 告訴服務注冊中心自己要下線了。服務端在接收到請求之后,將該服務狀態置為下線(DOWN), 並把該下線事件傳播出去。
服務注冊中心
1.失效剔除
服務實例並不一定會正常下線,可能由於內存溢出、網絡故障等原因使得服務不能正常工作,而服務注冊中心並未收到“服務下線” 的請求。為了從服務列表中將這些無法提供服務的實例剔除, Eureka Server在啟動的時候會創建一個定時任務,默認每隔一段時間(默認為60秒) 將當前清單中超時(默認為90秒)沒有續約的服務剔除出去。
2.自我保護機制
當我們在本地調試基於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.
事實上,該警告就是觸發了EurekaServer的自我保護機制。當服務注冊到EurekaServer之后,會維護一個心跳連接,告訴EurekaServer自己還活着。EurekaServer在運行期間,會統計心跳失敗的比例在15分鍾之內是否低於85%, 如果出現低於該值,Eureka Server會將當前的實例注冊信息保護起來,讓這些實例不會過期,盡可能保護這些注冊信息。但是,在這段保護期間內實例若出現問題,那么客戶端很容易拿到實際已經不存在的服務實例, 會出現調用失敗的清況,所以客戶端必須要有容錯機制,比如可以使用請求重試、斷路器等機制。
由於本地調試很容易觸發注冊中心的保護機制,這會使得注冊中心維護的服務實例不那么准確。所以,我們在本地進行開發的時候, 可以使用eureka.server.enableself-preservation=false
參數來關閉保護機制, 以確保注冊中心可以將不可用的實例正確剔除。