天天看點

Spring Cloud Eureka(用戶端)

上次我們講了

Spring Cloud Eureka

服務端,這次來說下用戶端。用戶端簡單來說就是把服務注冊到服務端

Eureka用戶端

主要處理服務的注冊和發現。用戶端服務通過注冊和參數配置的方式,嵌入在用戶端應用程式的代碼中。在應用程式啟動時,Eureka用戶端向服務注冊中心注冊自身提供的服務,并周期性的發送心跳來更新它的服務租約。同時,他也能從服務端查詢目前注冊的服務資訊并把它們緩存到本地并周期行的重新整理服務狀态。

服務注冊

服務提供者在啟動的時候會通過

REST

請求的方式将自己注冊到

Eureka Server

上,同時帶上自身服務的一些中繼資料資訊。

Eureka Server

接收到這個

Rest

請求之後,将中繼資料資訊存儲在一個雙層結構的

Map

中,其中第一層的

key

是服務名。第二層的

key

是具體服務的執行個體名。

在服務注冊時,需要确認一下

eureka.client.register-with-eureka=true

參數是否正确,該值預設為

true

。若設定為

fasle

将不會啟動注冊操作。一般

Eureka Server

才設定為

false

Eureka Client

都設為

true

服務同步

不同的服務提供者可以注冊在不同的服務注冊中心上,它們的資訊被不同的服務注冊中心維護。由于多個服務注冊中心互相注冊為服務,當服務提供者發送注冊請求到一個服務注冊中心時,它會将該請求轉發給叢集中相連的其他注冊中心,進而實作服務注冊中心之間的服務同步。通過服務同步,提供者的服務資訊就可以通過叢集中的任意一個服務注冊中心獲得。

建立并注冊服務提供者

SpringCloud

SpringBoot

的版本在上一篇文章有,這裡我就不多說了

在微服務項目中,在同一個項目中應該建立多個子產品,每個子產品對應不同的服務

引入

Spring Cloud Eureka Client

依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
           

開啟Eureka用戶端

隻需要在啟動類中加入

@EnableEurekaClient

注解

@SpringBootApplication
@EnableEurekaClient
public class SpringcloudEurekaClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringcloudEurekaClientApplication.class, args);
    }
}
           

在配置檔案中加入

Eureka Client

相關配置

需要指定服務注冊中心的位址

server:
  port: 8081
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9090/eureka
           

這裡的設定基本上都可以看懂吧,

server.port

指定服務的端口号

eureka.client.service-url.defaultZone

指定注冊中心的位址

擷取服務

消費者服務啟動時,會發送一個Rest請求給服務注冊中心,來擷取上面注冊的服務清單。為了性能考慮,

Eureka Server

會維護一份隻讀的服務注冊清單來傳回給用戶端,同時該緩存清單預設會每隔30秒更新一次。

eureka.client.registery-fetch-interval-seconds

:從

Eureka

伺服器端擷取注冊資訊的間隔時間,機關:秒,預設是30秒(對于

api-gateway

,如果要迅速擷取服務注冊狀态,可以縮小該值,比如5秒)

eureka.client.eureka-server-connect-timeout-seconds

:連接配接

Eureka Server

的逾時時間,機關:秒,預設是5秒

eureka.client.eureka-server-read-timeout-seconds

:讀取

Eureka Server

資訊的逾時時間,機關:秒,預設是8秒

eureka.client.filter-only-up-instances

:擷取執行個體時是否過濾,隻保留

UP

狀态的執行個體,預設為

true

eureka.client.eureka-connection-idle-timeout-seconds

:

Eureka 服務端連接配接空閑關閉時間,機關:秒,預設是30秒

eureka.client.eureka-server-total-connections

Eureka

用戶端到所有

Eureka

服務端的連接配接總數,預設是200

eureka.client.eureka-server-total-connections-per-host

Eureka

用戶端到每個

Eureka

服務主機的連接配接總數,預設是50

服務調用

服務消費者在擷取服務清單後,通過服務名可以擷取具體提供服務的執行個體名和該執行個體的中繼資料資訊。因為有這些服務執行個體的詳細資訊,是以用戶端可以根據自己的需要決定具體調用哪個執行個體,在

Ribbon

中會預設采用輪詢的方式進行調用,進而實作用戶端的負載均衡。

服務下線

在系統運作過程中必然會面臨關閉或重新開機服務的某個執行個體的情況,在服務關閉操作時,會觸發一個服務下線的

Rest

服務請求給

Eureka Server

,告訴服務注冊中心該服務下線了。服務端在接收到該請求後,将該服務狀态置位下線

(DOWN)

,并把該下線事件傳播出去。

服務啟動

一定要先啟動

Eureka Server

再啟動

Eureka Client

不然會報

com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server

意思就是找不到服務端

注:

我在測試的時候沒加

web

依賴同樣是報找不到服務端,是以還是加上吧

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
           

成功啟動之後,在浏覽器輸入

http://localhost:9090/

就可以進入服務注冊中心,如果設了安全驗證就需要使用者密碼,上一篇文章有說到

QQ截圖20180615205232.png

在服務注冊中心中可以看到服務中有一個名為

unknown

的應用服務,開放的端口是

8081

,證明我們的服務成功注冊了

來改下應用名吧,

unknown

是預設名

隻需要在配置檔案中配置

spring.application.name

就可以了

spring:
  application:
    name: springcloud-eureka-client
           

下面重新啟動下

Eureka Client

,重新整理下服務注冊中心頁面

QQ截圖20180615210040.png

可以看到名為

springcloud-eureka-client

的服務已經注冊上去了,但是之前的

unknown

服務還沒下線,是以報了上面紅色的一段話

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.

如果在Eureka Server的首頁看到這段提示,則說明Eureka已經進入了保護模式,一般出現此模式時,服務傳回錯誤。即如果真實的服務已經Down掉,但在注冊中心界面服務卻一直存在,且顯示為UP狀态。

産生原因:

Eureka Server

在運作期間,會統計心跳失敗的比例在15分鐘之内是否低于85%,如果出現低于的情況(在單機調試的時候很容易滿足,實際在生産環境上通常是由于網絡不穩定導緻),

Eureka Server

會将目前的執行個體注冊資訊保護起來,同時提示這個警告。保護模式主要用于一組用戶端和

Eureka Server

之間存在網絡分區場景下的保護。一旦進入保護模式,

Eureka Server

将會嘗試保護其服務系統資料庫中的資訊,不再删除服務系統資料庫中的資料(也就是不會登出任何微服務)。

解決方法:

1.重新啟動用戶端和服務端(不推薦,如果太多服務的話會很麻煩)

2.關閉注冊中心自我保護機制

Eureka Server

配置檔案中把

eureka.server.enable-self-preservation

設定為

false

不過設定了之後隻是看不到上面那段紅色的提示,并且還多了一條新的提示

THE SELF PRESERVATION MODE IS TURNED OFF.THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.

告訴我們自我保護機制被關閉了

當你再次進入服務注冊中心時,可能還是有兩個相同的服務,這個是正常的

因為預設情況下,如果

Eureka Server

在一定時間内(預設90秒)沒有接收到某個微服務執行個體的心跳,

Eureka Server

将會移除該執行個體。

我試過在用戶端的配置檔案中加入

eureka:
  instance:
    lease-renewal-interval-in-seconds: 1
    lease-expiration-duration-in-seconds: 2
           

lease-renewal-interval-in-seconds

每間隔1s,向服務端發送一次心跳,證明服務依然”存活“

lease-expiration-duration-in-seconds

告訴服務端,如果我2s之内沒有給服務端發心跳,就代表服務

down

掉了,将服務踢出掉。

但是還是隔了幾十秒才把

down

掉的服務移除,不知道是不是我網絡問題

是以我覺得在注冊服務時寫好服務名,最好不改,改了也沒多大問題,就是要等一會注冊中心才會把

down

掉的服務移除,自我保護機制我是推薦不關閉的。

是以正常的是這樣的

QQ截圖20180615211119.png

官方對于自我保護機制的說明

自我保護模式正是一種針對網絡異常波動的安全保護措施,使用自我保護模式能使

Eureka

叢集更加的健壯、穩定的運作。

自我保護機制的工作機制是如果在15分鐘内超過85%的用戶端節點都沒有正常的心跳,那麼

Eureka

就認為用戶端與注冊中心出現了網絡故障,

Eureka Server

自動進入自我保護機制,

此時會出現以下幾種情況:

1、

Eureka Server

不再從注冊清單中移除因為長時間沒收到心跳而應該過期的服務。

2、

Eureka Server

仍然能夠接受新服務的注冊和查詢請求,但是不會被同步到其它節點上,保證目前節點依然可用。

3、當網絡穩定時,目前

Eureka Server

新的注冊資訊會被同步到其它節點中。

是以

Eureka Server

可以很好的應對因網絡故障導緻部分節點失聯的情況,

而不會像

Zookeeper

那樣如果有一半不可用的情況會導緻整個叢集不可用而變成癱瘓。

關于開啟Eureka用戶端

上面我們使用的是

@EnableEurekaClient

其實

@EnableDiscoveryClient

@EnableEurekaClient

都是可以的

SpringCloud

中發現服務有許多種實作(eureka、consul、zookeeper等等)。

@EnableDiscoveryClient

基于

spring-cloud-commons

,

@EnableEurekaClient

spring-cloud-netflix

如果選用的注冊中心是

eureka

,那麼就推薦

@EnableEurekaClient

如果是其他的注冊中心,那麼推薦使用

@EnableDiscoveryClient