SpringCloud微服務註冊中心——Eureka
本文程式碼示例基於Spring Boot 2.0.7和Spring Cloud Finchley.SR2版本;
1. 服務發現
原來我們服務間的呼叫,一般都是通過在消費者端配置生產者的ip和埠,來進行呼叫,但是,在微服務的環境中,服務數量可能會很多,而且,服務之間可能呼叫關係也會很多,如果還是配置ip和埠來互相呼叫的話,這個配置的工作就很龐雜,同時,如果某個微服務的ip發生了變化,那麼帶來的維護工作,也會很複雜。
因此,微服務中引入了服務發現元件,也就是註冊中心,一般使用Eureka,也有其他的元件,Consul,zookeeper等。實際使用中,將微服務都註冊到註冊中心,註冊中已經包含了微服務的ip等資訊,這樣,微服務之間互相呼叫時,就可以現在註冊中心獲取對應微服務的ip資訊。這樣就不用自己維護很多的配置檔案了。
1.1 Eureka簡介
Eureka是Netflix開源的服務發現元件,本身是一個基於REST的服務,包含Server和Client兩部分,Spring Cloud將它整合在子專案Spring Cloud Netflix中。在微服務系統中,我們需要單獨建立一個Eureka Server作為註冊中心,其他的微服務就相當於客戶端,註冊到我們的註冊中心中。
2. Eureka的使用
2.1 基本使用
2.1.1 建立Eureka Server
- 建立一個Spring Boot專案,新增依賴,這裡使用版本是
Finchley.SR2
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
複製程式碼
- 啟動類上新增註解
@EnableEurekaServer
- 配置檔案
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://localhost:8761/eureka/
複製程式碼
配置解析:
eureka.client.register-with-eureka=false
表示是否將自己註冊到Eureka Server,預設值trueeureka.client.fetch-registry=false
表示是否從Eureka Server獲取資訊,預設值tureeureka.client.serviceUrl.defaultZone
: 表示Eureka Server的地址,如果有多個,使用逗號分隔。
2.1.2 建立一個微服務
- 建立一個Spring Boot專案,引入依賴,由於我使用的是
Finchley.SR2
版本,需要引入web依賴:
<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>
複製程式碼
- 啟動類新增註解
@EnableDiscoveryClient
該註解,從Edgware
版本開始,也可以省略不寫 - 配置檔案
server:
port: 8762
spring:
application:
name: auth-server
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
複製程式碼
spring.application.name
: 表示註冊到Eureka Server中服務名
啟動兩個服務,直接訪問Eureka Server地址,結果如圖
可以看到,服務註冊成功;這樣,如果有多個服務之間互相呼叫,就可以從Eureka Server中獲取到對應服務的資訊,這裡暫時先不演示; 但是,存在一個問題,服務註冊時,預設都是通過hostname來註冊的,也就是這裡的localhost,但是,如果服務不在同一個伺服器上,顯然是呼叫不了的,因此,我們再客戶端增加一個配置:- eureka.instance.prefer-ip-address=true : 表示將自己的ip註冊到Eureka Server。此時,雖然註冊中心皮膚上還是hostname,但是,實際訪問時已經時通過ip來訪問了。可以點選皮膚上status列上的連結驗證。
另外,如果客戶端所在的伺服器,有多個網路卡的情況下,使用這種方式,怎麼知道註冊哪個ip呢? Spring Cloud提供了按需選擇ip的能力:
- 忽略指定名稱的網路卡:
spring:
cloud:
inetutils:
ignoredInterfaces:
- docker0
- veth.*
- VM.*
複製程式碼
- 使用正規表示式,指定使用的網路地址:
spring:
cloud:
inetutils:
preferredNetworks:
- 192.168
複製程式碼
- 只是用站點本地地址:
spring:
cloud:
inetutils:
use-only-site-local-interfaces: true
複製程式碼
- 手動指定ip地址:
eureka:
instance:
ip-address: 127.0.0.1
複製程式碼
2.2 身份驗證
上邊的例子中,已經展示了Eureka的基本用法,其中Eureka的控制檯,只要輸入對應的ip和埠,就可以訪問,這肯定不符合企業的安全規範,一般情況下都是需要輸入一個使用者名稱和密碼;這裡展示簡單的使用Security來新增註冊中心的身份驗證:
- 引入security依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
複製程式碼
- 配置檔案中配置使用者名稱和密碼 2.0之前的配置
security:
basic:
enable: true # 開啟基於HTTP basic的認證
user:
name: root
password: root
複製程式碼
以上配置完成後,使用瀏覽器訪問Eureka Server,就會提示輸入使用者名稱和密碼,才能訪問;那麼,註冊中心增加了身份驗證之後,微服務要如何才能註冊呢? 微服務的註冊,只需要將配置Eureka Server的地址新增上使用者名稱和密碼就可以了,具體配置為:
eureka:
client:
service-url:
# http://username:password@EUREKA_HOST:EUREKA_PORT/eureka/
defaultZone: http://root:root@localhost:8761/eureka/
複製程式碼
由於,我使用的Spring Boot
版本為2.0.7.RELEASE
,Eureka Server配置需要稍作修改:
Spring Boot 2.0中security捨棄了一些配置,因此配置需要修改如下:
spring:
security:
user:
name: root
password: root
複製程式碼
然後,需要增加配置類,否則客戶端註冊會報錯,cannot execute any request on any know server:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
複製程式碼
2.3 自我保護
如果Eureka Server在一定時間內沒有收到微服務例項的心跳,會將該微服務登出,即從登錄檔中移除;但是,有時候因為網路或者其他的原因沒有收到心跳,例項還是正常可用,這種情況下,如果將例項從登錄檔中移除,訪問該微服務本來是應該正常了,卻導致了訪問失敗,造成系統的誤報同時難以排查問題; 為了防止上述情況發生,Eureka Server預設開啟了自我保護機制,如果短時間內,註冊中心丟失了過多的客戶端,Eureka Server會進入自我保護狀態,該狀態下,會保護登錄檔中的資訊,不會從登錄檔中刪除資料,也就是,雖然沒有收到微服務例項的心跳,但是,還會儲存該例項的註冊資訊,不會將之移除。 如果不想讓Eureka Server使用自我保護機制,我們可以在配置檔案中增加如下配置:
eureka:
server:
enable-self-preservation: false
複製程式碼
2.4 健康檢查
根據前文中圖片,微服務例項的狀態對應的是UP,表示該服務可用;我們也知道了Eureka Server通過心跳來驗證微服務是否正常;但是,有時候微服務正常執行,也不一定可用,可能微服務中的某個元件不可用,或者,資料來源連線不上,導致微服務不可用;但是,Eureka Server通過心跳並不能獲取這些資訊,還是會顯示UP狀態,因此,我們還需要對客戶端進行健康檢查。 微服務的健康檢查,基於actuator包,因此,在客戶端需要引入依賴,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
複製程式碼
(ps: 引入依賴後,啟動類微服務,在IDE控制檯可以看到,增加了幾個請求路徑,/actuator/health
,/actuator/info
等,Spring Boot 2.0之前可能是/health,/info;我們可以手動請求該路徑,檢視微服務的健康狀態)
然後,增加配置,啟動健康檢查,將健康狀態傳播到Eureka Server
eureka:
client:
healthcheck:
enabled: true
複製程式碼
2.5 Eureka Server的高可用
前文描述的Eureka Server都是單機狀態,如果,我們想要實現高可用,搭建Eureka Server叢集,也非常簡單,只需要將Eureka Server作為微服務註冊到其他的Server中;其他的微服務註冊,原來的地址直接配置多個就可以了,使用逗號分隔,例如:
eureka:
client:
service-url:
defaultZone: http://username:password@localhost:8761/eureka/,http://username:password@localhost:8762/eureka
複製程式碼
Eureka Server和普通的微服務例項配置類似,只是url中,不包含自己的,也就是前文所說的註冊到其他的Server。