SpringCloud----服務註冊中心Eureka
一 Eureka服務治理體系
1.1 服務治理
服務治理是微服務架構中最為核心和基礎的模組,它主要用來實現各個微服務例項的自動化註冊和發現。
Spring Cloud Eureka是Spring Cloud Netflix微服務套件中的一部分,它基於Netflix Eureka做了二次封裝。主要負責完成微服務架構中的服務治理功能。
Eureka服務治理體系如下:
1.2 服務註冊
在服務治理框架中,通常都會構建一個註冊中心,每個服務單元向註冊中心登記自己提供的服務,包括服務的主機與埠號、服務版本號、通訊協議等一些附加資訊。註冊中心按照服務名分類組織服務清單,同時還需要以心跳檢測的方式去監測清單中的服務是否可用,若不可用需要從服務清單中剔除,以達到排除故障服務的效果。
1.3 服務發現
在服務治理框架下,服務間的呼叫不再通過指定具體的例項地址來實現,而是通過服務名發起請求呼叫實現。服務呼叫方通過服務名從服務註冊中心的服務清單中獲取服務例項的列表清單,通過指定的負載均衡策略取出一個服務例項位置來進行服務呼叫。
二 Netflix Eureka
2.1 Netflix Eureka介紹
Spirng Cloud Eureka使用Netflix Eureka來實現服務註冊與發現。它既包含了服務端元件,也包含了客戶端元件,並且服務端與客戶端均採用java編寫,所以Eureka主要適用於通過java實現的分散式系統,或是JVM相容語言構建的系統。Eureka的服務端提供了較為完善的REST API,所以Eureka也支援將非java語言實現的服務納入到Eureka服務治理體系中來,只需要其他語言平臺自己實現Eureka的客戶端程式。目前.Net平臺的Steeltoe、Node.js的eureka-js-client等都已經實現了各自平臺的Ereka客戶端元件。
2.2 Eureka服務端
Eureka服務端,即服務註冊中心。它同其他服務註冊中心一樣,支援高可用配置。依託於強一致性提供良好的服務例項可用性,可以應對多種不同的故障場景。
Eureka服務端支援叢集模式部署,當叢集中有分片發生故障的時候,Eureka會自動轉入自我保護模式。它允許在分片發生故障的時候繼續提供服務的發現和註冊,當故障分配恢復時,叢集中的其他分片會把他們的狀態再次同步回來。叢集中的的不同服務註冊中心通過非同步模式互相複製各自的狀態,這也意味著在給定的時間點每個例項關於所有服務的狀態可能存在不一致的現象。
2.3 Eureka客戶端
Eureka客戶端,主要處理服務的註冊和發現。客戶端服務通過註冊和引數配置的方式,嵌入在客戶端應用程式的程式碼中。在應用程式啟動時,Eureka客戶端向服務註冊中心註冊自身提供的服務,並週期性的傳送心跳來更新它的服務租約。同時,他也能從服務端查詢當前註冊的服務資訊並把它們快取到本地並週期行的重新整理服務狀態。
三 服務註冊中心
3.1 服務註冊中心功能概述
在服務治理框架中,通常都會構建一個註冊中心,每個服務單元向註冊中心登記自己提供的服務,包括服務的主機與埠號、服務版本號、通訊協議等一些附加資訊。註冊中心按照服務名分類組織服務清單,同時還需要以心跳檢測的方式去監測清單中的服務是否可用,若不可用需要從服務清單中剔除,以達到排除故障服務的效果。
3.2 建立Eureka Server服務
建立一個Spring Boot工程,命名為Eureka-Server,並在pom檔案中引入依賴:
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
3.3 Eureka Server相關配置
在預設配置下,Eureka Server會將自己也作為客戶端來嘗試註冊自己,我們需要禁用它的客戶端禁用行為。
下面是一個Eureka Server的application.properites的相關配置:
#服務註冊中心埠號 server.port=1110 #服務註冊中心例項的主機名 eureka.instance.hostname=localhost #是否向服務註冊中心註冊自己 eureka.client.register-with-eureka=false #是否檢索服務 eureka.client.fetch-registry=false #服務註冊中心的配置內容,指定服務註冊中心的位置 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
更多引數配置資訊可參考:https://blog.csdn.net/zhangchangbin123/article/details/80026248
3.4 啟動服務註冊中心
通過@EnableEurekaServer註解啟動服務註冊中心,如下:
@EnableEurekaServer @SpringBootApplication public class IefopEurekaServerApplication { publicstatic void main(String[] args) { SpringApplication.run(IefopEurekaServerApplication.class,args); } }
3.5 高可用服務註冊中心
3.5.1 高可用服務註冊中心的概念
考慮到發生故障的情況,服務註冊中心發生故障必將會造成整個系統的癱瘓,因此需要保證服務註冊中心的高可用。
Eureka Server在設計的時候就考慮了高可用設計,在Eureka服務治理設計中,所有節點既是服務的提供方,也是服務的消費方,服務註冊中心也不例外。
Eureka Server的高可用實際上就是將自己做為服務向其他服務註冊中心註冊自己,這樣就可以形成一組互相註冊的服務註冊中心,以實現服務清單的互相同步,達到高可用的效果。
3.5.2 構建服務註冊中心叢集
Eureka Server的同步遵循著一個非常簡單的原則:只要有一條邊將節點連線,就可以進行資訊傳播與同步。可以採用兩兩註冊的方式實現叢集中節點完全對等的效果,實現最高可用性叢集,任何一臺註冊中心故障都不會影響服務的註冊與發現
在搭建 Eureka 叢集時,需要新增多個配置檔案,並且使用 SpringBoot 的多環境配置方式。叢集中需要多少節點就新增多少個配置檔案。
(1)建立application-peer1.properties
server.port=1111 eureka.instance.hostname=master spring.application.name=eureka-server eureka.client.serviceUrl.defaultZone=http://backup1:1112/eureka/,http://backup2:1113/eureka/
(2)建立application-peer2.properties
server.port=1112 eureka.instance.hostname=backup1 spring.application.name=eureka-server eureka.client.serviceUrl.defaultZone=http://master:1111/eureka/,http://backup2:1113/eureka/
(3)建立application-peer3.properties
server.port=1113 eureka.instance.hostname=backup2 spring.application.name=eureka-server eureka.client.serviceUrl.defaultZone=http://master:1111/eureka/,http://backup1:1112/eureka/
(4) 在hosts檔案中增加如下配置
127.0.0.1 master
127.0.0.1 backup1
127.0.0.1 backup2
方式一:在linux環境下:
vim /etc/hosts
127.0.0.1 master
127.0.0.1 backup1
127.0.0.1 backup2
方式二:在Windows本地:
Windows的hosts路徑為:C:\Windows\System32\drivers\etc,在hosts檔案中增加配置內容
3.6 失效剔除
有些時候,我們的服務例項並不一定會正常下線,可能由於記憶體溢位、網路故障等原因使服務不能正常運作。而服務註冊中心並未收到“服務下線”的請求,為了從服務列表中將這些無法提供服務的例項剔除,Eureka Server在啟動的時候會建立一個定時任務,預設每隔一段時間(預設為60秒)將當前清單中超時(預設為90秒)沒有續約的服務剔除出去。
3.7 自我保護
服務註冊到Eureka Server後,會維護一個心跳連線,告訴Eureka Server自己還活著。Eureka Server在執行期間會統計心跳失敗的比例在15分鐘以之內是否低於85%,如果出現低於的情況,Eureka Server會將當前例項註冊資訊保護起來,讓這些例項不會過期。這樣做會使客戶端很容易拿到實際已經不存在的服務例項,會出現呼叫失敗的情況。因此客戶端要有容錯機制,比如請求重試、斷路器。
以下是自我保護相關的屬性:
eureka.server.enableSelfPreservation=true. 可以設定改引數值為false,以確保註冊中心將不可用的例項刪除
3.8 region(地域)與zone(可用區)
region和zone(或者Availability Zone)均是AWS的概念。在非AWS環境下,我們可以簡單地將region理解為地域,zone理解成機房。一個region可以包含多個zone,可以理解為一個地域內的多個不同的機房。不同地域的距離很遠,一個地域的不同zone間距離往往較近,也可能在同一個機房內。
region可以通過配置檔案進行配置,如果不配置,會預設使用us-east-1。同樣Zone也可以配置,如果不配置,會預設使用defaultZone。
Eureka Server通過eureka.client.serviceUrl.defaultZone屬性設定Eureka的服務註冊中心的位置。
指定region和zone的屬性如下:
(1)eureka.client.availabilityZones.myregion=myzone# myregion是region
(2)eureka.client.region=myregion
Ribbon的預設策略會優先訪問通客戶端處於同一個region中的服務端例項,只有當同一個zone中沒有可用服務端例項的時候才會訪問其他zone中的例項。所以通過zone屬性的定義,配合實際部署的物理結構,我們就可以設計出應對區域性故障的容錯叢集。
3.9 安全驗證
我們啟動了Eureka Server,然後在瀏覽器中輸入http://127.0.0.1:1110/後,直接回車,就進入了spring cloud的服務治理頁面,這麼做在生產環境是極不安全的,下面,我們就給Eureka Server加上安全的使用者認證.
(1)pom檔案中引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
(2)Eureka的配置資訊serviceurl中加入安全校驗資訊
eureka.client.serviceUrl.defaultZone=http://<username>:<password>@${eureka.instance.hostname}:${server.port}/eureka/
3.10 Eureka資訊面板
服務啟動後,訪問http://127.0.0.1:1110/可以看到Eureka的資訊面板。
四 服務提供者
4.1 服務註冊
服務提供者在啟動的時候會通過REST請求的方式將自己註冊到Eureka Server上,同時帶上自身服務的一些元資料資訊。Eureka Server接收到這個Rest請求之後,將元資料資訊儲存在一個雙層結構的Map中,其中第一層的key是服務名。第二層的key 是具體服務的例項名。
在服務註冊時,需要確認一下eureka.client.register-with-eureka=true引數是否正確,該值預設為true。若設定為fasle將不會啟動註冊操作。
4.2 服務同步
從eureka服務治理體系架構圖中可以看到,不同的服務提供者可以註冊在不同的服務註冊中心上,它們的資訊被不同的服務註冊中心維護。
此時,由於多個服務註冊中心互相註冊為服務,當服務提供者傳送註冊請求到一個服務註冊中心時,它會將該請求轉發給叢集中相連的其他註冊中心,從而實現服務註冊中心之間的服務同步。通過服務同步,提供者的服務資訊就可以通過叢集中的任意一個服務註冊中心獲得。
4.3 服務續約
在註冊服務之後,服務提供者會維護一個心跳用來持續高速Eureka Server,“我還在持續提供服務”,否則Eureka Server的剔除任務會將該服務例項從服務列表中排除出去。我們稱之為服務續約。
下面是服務續約的兩個重要屬性:
(1)eureka.instance.lease-expiration-duration-in-seconds
leaseExpirationDurationInSeconds,表示eureka server至上一次收到client的心跳之後,等待下一次心跳的超時時間,在這個時間內若沒收到下一次心跳,則將移除該instance。
預設為90秒
如果該值太大,則很可能將流量轉發過去的時候,該instance已經不存活了。
如果該值設定太小了,則instance則很可能因為臨時的網路抖動而被摘除掉。
該值至少應該大於leaseRenewalIntervalInSeconds
(2)eureka.instance.lease-renewal-interval-in-seconds
leaseRenewalIntervalInSeconds,表示eureka client傳送心跳給server端的頻率。如果在leaseExpirationDurationInSeconds後,server端沒有收到client的心跳,則將摘除該instance。除此之外,如果該instance實現了HealthCheckCallback,並決定讓自己unavailable的話,則該instance也不會接收到流量。
預設30秒
4.4 建立並註冊服務提供者
4.4.1 建立Eureka客戶端服務
建立一個Spring Boot工程,命名問Eureka-Client,並在pom檔案中引入依賴:
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
4.4.2 Eureka Client相關配置
在Eureka客戶端需要在application.properties檔案中指定服務註冊中心的地址
eureka.port=1110 eureka.instance.hostname=localhost #在此指定服務註冊中心地址 eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${eureka.port}/eureka/
4.4.3 啟動Eureka客戶端
在主類中加入@EnableEurekaClient註解啟動Eureka客戶端,如下:
@EnableEurekaClient @SpringBootApplication public class IefopEurekaClientApplication { publicstatic void main(String[] args) { SpringApplication.run(IefopEurekaClientApplication.class,args); } }
五 服務消費者
5.1 獲取服務
消費者服務啟動時,會發送一個Rest請求給服務註冊中心,來獲取上面註冊的服務清單。為了效能考慮,Eureka Server會維護一份只讀的服務註冊清單來返回給客戶端,同時該快取清單預設會每隔30秒更新一次。
下面是獲取服務的兩個重要的屬性:
(1)eureka.client.fetch-registry
是否需要去檢索尋找服務,預設是true
(2)eureka.client.registry-fetch-interval-seconds
表示eureka client間隔多久去拉取服務註冊資訊,預設為30秒,對於api-gateway,如果要迅速獲取服務註冊狀態,可以縮小該值,比如5秒
5.2 服務呼叫
服務消費者在獲取服務清單後,通過服務名可以獲取具體提供服務的例項名和該例項的元資料資訊。因為有這些服務例項的詳細資訊,所以客戶端可以根據自己的需要決定具體呼叫哪個例項,在Ribbon中會預設採用輪詢的方式進行呼叫,從而實現客戶端的負載均衡。
5.3 服務下線
在系統執行過程中必然會面臨關閉或重啟服務的某個例項的情況,在服務關閉操作時,會觸發一個服務下線的Rest服務請求給Eureka Server,告訴服務註冊中心:“我要下線了。”服務端在接收到該請求後,將該服務狀態置位下線(DOWN),並把該下線事件傳播出去。
六 服務例項類配置
6.1 端點配置
eureka例項的狀態頁面和健康監控的url預設為spring boot actuator提供的/info端點和/health端點。我們必須確保Eureka客戶端的/health端點在傳送元資料的時候,是一個能夠被註冊中心訪問到的地址,否則服務註冊中心不會根據應用的健康檢查來更改狀態(僅當開啟了healthcheck功能時,以該端點資訊作為健康檢查標準)。而如果/info端點不正確的話,會導致在Eureka面板中單擊服務時,無法訪問到服務例項提供的資訊介面。
大多數情況下,我們不需要修改這個幾個url配置。但是當應用不使用預設的上下文(context path或servlet path,比如配置server.servletPath=/test),或者管理終端路徑(比如配置management.contextPath=/admin)時,我們需要修改健康檢查和狀態頁的url地址資訊。
application.properties配置檔案如下:
server.context-path=/helloeureka //下面配置為相對路徑,也支援配置成絕對路徑,例如需要支援https eureka.instance.health-check-url-path=${server.context-path}/health eureka.instance.status-page-url-path=${server.context-path}/info
6.2 元資料
元資料是Eureka客戶端在向服務註冊中心傳送註冊請求時,用來描述自身服務資訊的物件,其中包含了一些標準化的元資料,比如服務名稱、例項名稱、例項IP、例項埠等用於服務治理的重要資訊;以及一些用於負載均衡策略或是其他特殊用途的自定義元資料資訊。
我們可以通過eureka.instance.<properties>=<value>的格式對標準化元資料直接進行配置,其中<properties>就是EurekaInstanceConfigBean物件中的成員變數。而對於自定義元資料,可以通過eureka.instance.metadataMap.<key>=<value>的格式來進行配置。比如:
eureka.instance.metadataMap.zone=tianjin //隨機生成例項名 eureka.instance.metadataMap.instanceId=${spring.application.name}:${random.value}
6.3 健康檢測
預設情況下,Eureka中各個服務例項的健康檢測並不是通過spring-boot-acturator模組的/health端點來實現的,而是依靠客戶端心跳的方式來保持服務例項的存活。在Eureka的服務續約與剔除機制下,客戶端的健康狀態從註冊到註冊中心開始都會處於UP狀態,除非心跳終止一段時間之後,服務註冊中心將其剔除。預設的心跳實現方式可以有效檢查客戶端程序是否正常運作,但卻無法保證客戶端應用能夠正常提供服務。
在Spring Cloud Eureka中,可以把Eureka客戶端的健康檢測交給spring-boot-actuator模組的health端點,以實現更加全面的健康狀態維護,設定方式如下:
(1)在pom.xml中引入spring-boot-starter-actuator模組的依賴
(2)在application.properties中增加引數配置eureka.client.healthcheck.enabled=true
6.4 其他配置
除了上述配置引數外,下面整理了一些EurekaInstanceConfigBean中定義的配置引數以及對應的說明和預設值,這些引數均以eureka.instance為字首。
七 通訊協議
預設情況下,Eureka使用Jersey和XStream配合JSON作為Server與Client之間的通訊協議。也可以選擇實現自己的協議來代替。