上次我們講了 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