Eureka 健康管理
簡述:
重新回顧一下艘希,Eureka的作用是什么届良。將一個復(fù)雜的應(yīng)用拆分成N各模塊竟贯,而模塊之間需要相互通信,那么各個模塊的通信服務(wù)需統(tǒng)一放置烹笔、存儲在一個地方裳扯,以提供給其他模塊獲取。
什么是模塊的“健康”
在上一節(jié)谤职,實(shí)現(xiàn)了“心跳管理”饰豺,其實(shí)就是Eureka服務(wù)列表的管理,實(shí)現(xiàn)了服務(wù)的“有”允蜈、“無”管理冤吨,即:判斷服務(wù)是否存在、從而刷新本地服務(wù)列表饶套。但是漩蟆,如果存在的服務(wù)是不健康的呢?比如妓蛮,該服務(wù)模塊需要連接數(shù)據(jù)庫怠李,但是數(shù)據(jù)庫服務(wù)掛掉宕機(jī)了,那么這個模塊就不能正常提供服務(wù)蛤克;故也應(yīng)告知其他其他模塊捺癞,讓其他模塊刪除對應(yīng)出現(xiàn)問題、標(biāo)記為“不健康”的服務(wù)构挤。
代碼實(shí)現(xiàn)髓介,還是以前例中App1、App2 為例筋现,
場景:App2 需要App1 提供服務(wù)唐础!
- 為App1添加依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
- 啟動Eureka服務(wù)、啟動App1
# 部分啟動日志如下
Mapped "{[/pause || /pause.json],me
Mapped "{[/metrics/{name:.*}],methoe
Mapped "{[/metrics || /metrics.json.
Mapped "{[/archaius || /archaius.jso
Mapped "{[/trace || /trace.json],meu
Mapped "{[/refresh || /refresh.json
Mapped "{[/health || /health.json],c
Mapped "{[/service-registry/instancs
Mapped "{[/service-registry/instancR
Mapped "{[/restart || /restart.json
Mapped "{[/resume || /resume.json],
Mapped "{[/autoconfig || /autoconfik
Mapped "{[/info || /info.json],metht
Mapped "{[/beans || /beans.json],meu
Mapped "{[/dump || /dump.json],metht
Mapped "{[/configprops || /configpro
Mapped "{[/loggers/{name:.*}],methoe
Mapped "{[/loggers/{name:.*}],methol
Mapped "{[/loggers || /loggers.json.
Mapped "{[/auditevents || /auditeveE
Mapped "{[/features || /features.jso
Mapped "{[/env/{name:.*}],methods=[d
Mapped "{[/env || /env.json],method.
Mapped "{[/heapdump || /heapdump.jso
Mapped "{[/env],methods=[POST]}" ona
Mapped "{[/env/reset],methods=[POST(
Mapped "{[/mappings ||
# 即多了以上服務(wù)節(jié)點(diǎn)可訪問
訪問:http://192.168.198.2:8081/health 即:檢查模塊健康狀況矾飞, 頁面響應(yīng):
{"description":"Spring Cloud Eureka Discovery Client","status":"UP"}
訪問正常一膨,status 值為UP,說明模塊此時是健康的
訪問:http://192.168.198.2:8081/env 即查看所有環(huán)境變量洒沦,頁面響應(yīng):
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Mar 21 15:34:32 CST 2018
There was an unexpected error (type=Unauthorized, status=401).
Full authentication is required to access this resource.
# Unauthorized: 未經(jīng)授權(quán) 錯誤代碼:401
這是由于節(jié)點(diǎn)保護(hù)所引起的豹绪,關(guān)閉節(jié)點(diǎn)保護(hù),再App1 配置文件中添加如下屬性配置:
# 關(guān)閉節(jié)點(diǎn)保護(hù)
endpoints.sensitive=false
重啟App1微谓,再訪問 http://192.168.198.2:8081/env ,頁面響應(yīng):打印出該模塊所有環(huán)境變量输钩!
{"profiles":["8081"],"server.ports":{"local.server.port":8081},
……
訪問:http://192.168.198.2:8081/health 豺型,查看當(dāng)前節(jié)點(diǎn)的“健康狀態(tài)”,頁面響應(yīng):
{"status":"UP"}
# status 值為UP,說明該節(jié)點(diǎn)是健康的
訪問Eureka服務(wù)端 http://localhost:8761/ 頁面響應(yīng)
APPONE n/a (1) (1) UP (1) - localhost:AppOne:8081
# APPONE 狀態(tài)為:UP买乃,即:健康狀況正常
“不健康狀態(tài)”姻氨,如何將該節(jié)點(diǎn)表示?比如不能正常連接數(shù)據(jù)庫剪验、網(wǎng)絡(luò)故障肴焊、磁盤IO瓶頸等前联,這個時候就得將其聲明為不健康狀態(tài)。Eureka 提供了HealthIndicator接口娶眷,通過監(jiān)視該接口對象以達(dá)到更改節(jié)點(diǎn)狀態(tài)的目的似嗤,完整代碼如下:
@Component
public class MyHealthIndicator implements HealthIndicator {
public Health health() {
if(HelloController.isHealth){ //節(jié)點(diǎn)是否健康的判斷依據(jù),UP:健康
return new Health.Builder(Status.UP).build();
}
return new Health.Builder(Status.DOWN).build(); //DOWN: 不健康
}
}
寫個Controller届宠,控制節(jié)點(diǎn)健康狀態(tài):
# HelloController 類
public static boolean isHealth=true;
@GetMapping("/setHealth/{health}")
public @ResponseBody boolean setHealth(@PathVariable boolean health){
isHealth=health;
return health;
}
訪問:http://192.168.198.2:8081/setHealth/false 烁落,將節(jié)點(diǎn)狀態(tài)改為Down,頁面輸出:
false
訪問http://192.168.198.2:8081/health,查看節(jié)點(diǎn)狀態(tài):
{"status":"DOWN"}
# 狀態(tài)成功改為:down
但是豌注,訪問Eureka服務(wù)端 http://localhost:8761/伤塌,顯示的還是UP狀態(tài),服務(wù)端沒有更新轧铁,如何讓服務(wù)端更新每聪,客戶端應(yīng)實(shí)現(xiàn) HealthCheckHandler 接口,交由Spring管理:
@Component
class MyHealthHander implements HealthCheckHandler{
@Autowired
MyHealthIndicator myHealthIndicator;
public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus instanceStatus) {
Status status = myHealthIndicator.health().getStatus();
if (status.equals(Status.UP)){
return InstanceInfo.InstanceStatus.UP;
}else if(status.equals(Status.DOWN)){
return InstanceInfo.InstanceStatus.DOWN;
}
return InstanceInfo.InstanceStatus.UNKNOWN;
}
}
默認(rèn)時間間隔是30s齿风,配置文件中應(yīng)添加如下配置药薯,將更新時間縮短
# 健康狀態(tài)注冊更新時間
eureka.instance.instanceInfoReplicationIntervalSeconds=10
重啟App1,訪問 http://192.168.198.2:8081/setHealth/false聂宾,節(jié)點(diǎn)狀態(tài)改為down
APPONE n/a (1) (1) DOWN (1) - 192.168.198.2:AppOne:8081
# 幾點(diǎn)狀態(tài)成功改為Down
啟動App2果善,訪問 http://192.168.198.2:8083/discoveryClientInstanceList
[{"apptwo":{"port":8083,"host":"192.168.198.2","serviceId":"APPTWO","uri":"http://192.168.198.2:8083"}}]
# 可知,只獲取到了一個實(shí)例
訪問:http://192.168.198.2:8083/getAppOneMesg/123456系谐,檢測App1是否能正常提供服務(wù)巾陕,頁面打印:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Mar 26 11:17:33 CST 2018
There was an unexpected error (type=Internal Server Error, status=500).
No instances available for APPONE
# No instances available for APPONE 沒有可用的APPONE 實(shí)例
訪問 http://192.168.198.2:8081/setHealth/true 纪他,將節(jié)點(diǎn)狀態(tài)改為健康鄙煤,等待,App2 刷新服務(wù)列表茶袒,重新訪問 http://192.168.198.2:8083/discoveryClientInstanceList
[{"appone":{"port":8081,"host":"192.168.198.2","serviceId":"APPONE","uri":"http://192.168.198.2:8081"}},{"apptwo":{"port":8083,"host":"192.168.198.2","serviceId":"APPTWO","uri":"http://192.168.198.2:8083"}}]
# 成功獲取兩個實(shí)例
訪問 http://192.168.198.2:8083/getAppOneMesg/123456梯刚,檢查App1 是否能成功提供服務(wù),頁面打有皆ⅰ:
訪問App2,從App1 收到信息:“808149,50,51,52,53,54,”
# 服務(wù)正常
本節(jié)配置梳理:
# 健康狀態(tài)注冊更新時間
eureka.instance.instanceInfoReplicationIntervalSeconds=10