Spring Cloud(一):服務註冊中心Eureka
Spring Cloud 基於 Netflix 的幾個開源專案進行了封裝,提供包括服務註冊與發現(Eureka),智慧路由(Zuul),熔斷器(Hystrix),客戶端負載均衡(Ribbon)等在內的核心元件。
在微服務系統中,服務少則十幾、幾十個,多則上百、幾百個(據悉 Netflix 的雲平臺上運行了500多個微服務),這些微服務通過相互呼叫來為使用者提供功能。那麼一個服務呼叫另一個服務是如何進行的,如何定位到另一個服務的地址?程式碼中寫死,還是配置檔案中配置?顯然對於服務數量較多的系統,這兩種方式先不說後續維護,光寫起來就很痛苦。於是,對於微服務架構來說,服務的自動註冊與發現就成為非常核心的功能,Eureka就是來負責實現這個功能的。
本系列文章與示例均基於最新的Spring Cloud Hoxton版編寫。
Eureka
Eureka是一個基於REST的服務,包括Eureka Server與Eureka Client兩個端。Eureka Server作為服務註冊中心接受Eureka Client的註冊及獲取其它服務的地址資訊。基本架構如下圖所示:
其中
-
Eureka Server: 作為服務註冊中心,提供服務註冊與發現功能介面
-
Service Provider: 服務提供者,將自身服務註冊到服務註冊中心,供其它服務消費者發現與呼叫
-
Service Consumer: 服務消費者,從服務註冊中心發現服務,並通過一些負載均衡客戶端來呼叫(比如Ribbon或Feign)
很多時候同一個應用可能既是服務提供者,也是服務消費者——自己作為服務方,為其它服務提供介面,同時也呼叫其它服務的介面來完成自身的業務邏輯。
Eureka Server
Eureka Server的搭建非常簡單,其部署可分為單例項部署與多例項叢集部署,一般開發測試環境可以使用單例項部署,但生產環境出於高可用要求,可進行多例項叢集部署。
1. 在pom.xml中新增依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency>
為了方便版本引入,可以在pom中新增依賴管理,這樣spring cloud相關的starter依賴就不需要指定版本了(如上省略了version)
<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>
2. 在啟動類上添加註解 @EnableEurekaServer
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
3. 在application.yml 或 application.properties配置檔案中新增配置(個人比較傾向於yml,兩者區別可自行百度)
spring: application: name: spring-cloud-eureka profiles: active: single server: port: 8761 --- spring: profiles: single eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ --- spring: profiles: peer1 server: port: 8761 eureka: instance: hostname: peer1 client: serviceUrl: defaultZone: http://peer2:8762/eureka/,http://peer3:8763/eureka/ --- spring: profiles: peer2 server: port: 8762 eureka: instance: hostname: peer2 client: serviceUrl: defaultZone: http://peer1:8761/eureka/,http://peer3:8763/eureka/ --- spring: profiles: peer3 server: port: 8763 eureka: instance: hostname: peer3 client: serviceUrl: defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/
eureka.client.registerWithEureka
:表示是否將自身註冊到Eureka Server,預設為true,單例項模式下一般設定為false,否則會在啟動時報連線不到伺服器的錯誤在該配置檔案中,實際上是定義了兩種模式,其中預設的profile single是單例項模式, peer1, peer2, peer3組成多例項模式。
-
eureka.client.fetchRegistry
:表示是否從Eureka Server獲取註冊服務列表,預設為true,同樣在單例項模式下設定為false -
eureka.client.serviceUrl.defaultZone
:Eureka Server的地址,多例項模式下多個地址以“,”隔開,多個例項之間只要有一條路線連通,則總會將註冊資訊進行同步
4. 啟動
對於單例項模式,如果按如上配置,則直接啟動程式即可。啟動完成後,訪問 http://localhost:8761,即可檢視Eureka Server的相關資訊,如
上圖所示,當前沒有Eureka Server的副本也沒有任何服務註冊。
對於多例項叢集模式,則需要根據不同的profile啟動多個例項,
mvn clean package cd target java -jar springcloud-eureka-1.0-SNAPSHOT.jar --spring.profiles.active=peer1 java -jar springcloud-eureka-1.0-SNAPSHOT.jar --spring.profiles.active=peer2 java -jar springcloud-eureka-1.0-SNAPSHOT.jar --spring.profiles.active=peer3
啟動完成後,開啟 http://localhost:8761, 可以看到Eureka Server已經存在副本與註冊的服務了(Eureka將自身作為一個服務完成了註冊)
上述操作如果是在單機進行,則需要在hosts檔案中新增對映,linux下是/etc/hosts,windows10 下是C:\Windows\System32\drivers\etc\hosts,
127.0.0.1 peer1 127.0.0.1 peer2 127.0.0.1 peer3
Eureka Client
Eureka Client一般整合在各個微服務中,整合也非常簡單。
1. pom.xml中新增依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2. application.yml配置檔案中新增配置
eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ instance: prefer-ip-address: true instance-id: ${spring.application.name}:${random.uuid}
如果是多例項叢集模式,則 eureka.client.serviceUrl.defaultZone
可以配置多個地址,“,”號分隔。
-
eureka.client.*
:發現服務的配置引數 -
eureka.instance.*
:註冊服務的配置引數, 如上eureka.instance.prefer-ip-address
設定為true表示服務註冊時使用IP,而不是hostname;eureka.instance.instance-id
配置服務例項的ID,預設為 ${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}}
添加了依賴就能整合Eureka Client,主類上新增 @EnableDiscoveryClient 註解不是必須。
啟動程式後,進入Eureka Server頁面即可看到註冊的服務
一些知識點(建議掌握)
-
Eureka Client在註冊服務時,提供包括hostname,IP地址, port, health indicator url,status page, home page 等在內的meta-data,其它客戶端可通過這些資訊來直接與服務進行互動,我們也可以通過
eureka.instance.metadataMap
來新增自定義的meta-data,供客戶端訪問。 -
Eureka Server通過接收Eureka Client的心跳訊息來判斷服務例項是否存活,如果某一個例項的心跳在特定時間(可配置)內沒收到,則將其從登錄檔中移除。心跳預設間隔為30s,一個服務被其它客戶端發現,可能需要經過3次心跳,這也是有時候服務註冊比較慢的原因。可通過
eureka.instance.leaseRenewalIntervalInSeconds
配置,但生產環境建議最好保持預設。 -
Eureka Client預設不會傳播當前應用的健康檢查狀態,一旦註冊成功,只要心跳存在,Eureka總是認為應用處於UP狀態。可以啟用Eureka的健康檢查,將狀態傳播給Eureka,其它應用只會將請求發給UP狀態的服務例項
eureka.client.healthcheck.enabled=true
。注意這個配置只能配置在application.yml中,配置在bootstrap.yml中可能導致註冊服務時,服務以狀態為UNKOWN進行註冊。 -
Eureka Server是沒有後端儲存的,服務例項需要通過心跳來更新註冊資訊,註冊資訊存於記憶體中,Eureka Client也有一個基於記憶體的快取,不需要每次請求服務都要訪問註冊中心獲取服務地址資訊。
-
Eureka的自我保護機制:Eureka Server在短時間內丟失比較多的客戶端時,會進入自我保護模式,在該模式下,Eureka Server即使發現服務例項已經不再發送心跳了,也不會從服務登錄檔中刪除。這樣,當發生網路故障時,服務註冊資訊仍然存於Eureka中,當網路故障恢復後,會自動退出自我保護模式。自我保護模式是一種應對網路異常的安全保護機制。相關配置:
eureka.server.renewal-percent-threshold
, 觸發自我保護機制的閾值,預設為0.85;eureka.server.enable-self-preservation
, 自我保護開啟,預設為true,如果設定為false,則關閉客戶端程式後,可直觀地從Eureka Server的頁面發現服務例項被登出刪除了。
本文示例程式碼
認真生活,快樂分享
歡迎關注公眾號:空山新雨的技術空間
有道詞典 <dependency> ... 詳細X <依賴> < groupId > org.springframework.cloud < / groupId > < artifactId > spring-cloud-starter-netflix-eureka-server < / artifactId > < / >的依賴