默認情況下,Eureka 客戶端每隔 30 秒會發送一次心跳給服務器端,告知正常存活,但是,實際環境中有可能出現這種情況,客戶端表面上可以正常發送心跳,但實際上服務是不可用的,例如,一個需要訪問數據的服務提供者,但是數據庫已經無法訪問了;或者依賴的第三方服務已經無法訪問了,對於這樣的情況應當告訴服務器當前客戶端的狀態,可以使用 Eureka 的健康檢查訪問控制器來實現。
Spring Boot Actuator
該模塊主要用於系統監控,當應用程序整合了 Actuator 后,就會自動提供多個服務端點,這些端點可以讓外部看到應用程序的健康狀況。在之前的服務提供者項目中,增加如下依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
啟動項目,並訪問 http://localhost:8080/health ,可以看到返回了系統自檢的內容,如下:
{"description":"Spring Cloud Eureka Discovery Client","status":"UP"}
自定義健康檢查
客戶端表面上可以正常發送心跳,但實際上服務是不可用的,例如,一個需要訪問數據的服務提供者,但是數據庫已經無法訪問了;或者依賴的第三方服務已經無法訪問了,這時就需要我們自己實現健康檢查,我們需要實現一個HealthIndicator,繼承 org.springframework.boot.actuate.health.HealthIndicator 接口;如果服務提供者希望把健康狀態告訴Eureka 服務端,則還需要實現一個自定義的 HealthCheckHandler(健康檢查處理器), HealthCheckHandler 會將應用的健康狀態保存到內存中,狀態一旦發生改變,就會重新向服務器進行注冊,示例如下:
-
創建自定義 HealthIndicator
package org.lixue.webservices.services;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator{
private int healthIndicatorErrorCount;
private int healthIndicatorCount;
private boolean hasError=false;
@Override
public Health health(){
if(!hasError){
healthIndicatorCount++;
//每檢測5次,就返回DOWN
if(healthIndicatorCount%5==0){
hasError=true;
}
}else{
//DOWN計數10次就UP
healthIndicatorErrorCount++;
if(healthIndicatorErrorCount>10){
hasError=false;
healthIndicatorErrorCount=0;
}
}
if(hasError){
return new Health.Builder(Status.DOWN).build();
}
return new Health.Builder(Status.UP).build();
}
}
-
創建自定義 HealthCheckHandler
package org.lixue.webservices.services;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Status;
import org.springframework.stereotype.Component;
@Component
public class MyHealthHealthCheckHandler implements HealthCheckHandler{
@Autowired
private MyHealthIndicator myHealthIndicator;
@Override
public InstanceInfo.InstanceStatus getStatus(InstanceInfo.InstanceStatus currentStatus){
Status status=myHealthIndicator.health().getStatus();
if(status==Status.UP){
returnInstanceInfo.InstanceStatus.UP;
}else{
returnInstanceInfo.InstanceStatus.DOWN;
}
}
}
-
啟動類增加自定義 healthIndicator 的Bean
@SpringBootApplication
@EnableDiscoveryClient
public class ServiceProviderApplication{
public static void main(String[]args){
SpringApplication.run(ServiceProviderApplication.class,args);
}
@Bean
public MyHealthIndicator myHealthIndicator(){
return new MyHealthIndicator();
}
}
-
測試驗證
啟動項目,Eureka 中會啟動一個定時器,定時刷新本地實例的信息,默認情況下,每隔30秒執行一次健康檢查,訪問我們的Eureka 服務端 http://eurekaserver01:9000 查詢服務提供者的狀態,可以看到經過5次健康檢查后,出現了 DOWN,表示我們的自定義健康檢查是正常運行的。