1 Hystrix 簡介
在微服務(wù)架構(gòu)中叶圃,微服務(wù)之間通過網(wǎng)絡(luò)進行通信,存在相互依賴践图,當(dāng)其中一個服務(wù)不可用時掺冠,有可能會造成雪崩效應(yīng)。要防止這樣的情況码党,必須要有容錯機制來保護服務(wù)德崭。
Hystrix是Netflix開源的一個延遲和容錯庫,它主要實現(xiàn)了以下幾點:
- 包裹請求
使用HystrixCommand(或HystrixObservableCommand)包裹對依賴的調(diào)用邏輯揖盘,每個命令在獨立線程中執(zhí)行眉厨。 - 跳閘機制
當(dāng)某服務(wù)的錯誤率超過一定閾值時,Hystrix可以自動或手動跳閘扣讼,停止請求該服務(wù)一段時間缺猛。 - 資源隔離
Hystrix為每個依賴都維護了一個小型的線程池(或信號量),如果該線程池已滿椭符,發(fā)往該依賴的請求就被立即拒絕荔燎。 - 監(jiān)控
Hystrix可以近乎實時地監(jiān)控運行指標(biāo)和配置的變化。 - 回退機制
當(dāng)請求失敗销钝、超時有咨、被拒絕,或者當(dāng)斷路器打開時蒸健,執(zhí)行回退邏輯座享。 - 自我修復(fù)
當(dāng)斷路器打開一段時間后,會自動進入“半打開”狀態(tài)似忧,允許一個請求訪問依賴的服務(wù)渣叛,如果該請求成功,則關(guān)閉斷路器盯捌,否則繼續(xù)保持打開狀態(tài)淳衙。
2 整合Hystrix
2.1 Ribbon整合Hystrix
1.添加相應(yīng)的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2.在啟動類里添加@EnableCircuitBreaker
或者 @EnableHystrix
注解
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class RibbonDemoApplication {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(RibbonDemoApplication.class, args);
}
}
3.為需要容錯的方法添加@HystrixCommand
注解,并使用fallbackMethod屬性指定回退方法
@HystrixCommand(fallbackMethod = "errorFallback")
@GetMapping("/hello")
public String hello() {
return this.restTemplate.getForObject("http://eureka-client-demo/hello", String.class);
}
public String errorFallback() {
return "Error!";
}
@HystrixCommand
的配置類似下面:
@HystrixCommand(fallbackMethod = "stubMyService",
commandProperties = {
@HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
}
)
2.2 Feign使用Hystrix
1.Spring Cloud 中饺著,F(xiàn)eign默認已經(jīng)整合了Hystrix箫攀,所以只需要在配置中啟用Hystrix就會包裹全部Feign Client中的方法:
feign:
hystrix:
enabled: true
2.編寫回退方法,編寫一個Feign Client的實現(xiàn)類幼衰,在@FeignClient
的fallback屬性指定對應(yīng)的類:
@FeignClient(name = "eureka-client-demo", fallback = ErrorFallback.class)
public interface DemoFeignClient {
@GetMapping("/hello")
public String hello();
}
@Component
public class ErrorFallback implements DemoFeignClient {
@Override
public String hello() {
return "Error!";
}
}
3.如果需要回退方法打印錯誤信息靴跛,可以使用fallbackFactory(fallback和fallbackFactory只能使用其中一種):
@FeignClient(name = "eureka-client-demo", fallbackFactory = ErrorFallbackFactory.class)
public interface DemoFeignClient {
@GetMapping("/hello")
public String hello();
}
@Component
public class ErrorFallbackFactory implements FallbackFactory<DemoFeignClient> {
private static final Logger LOGGER = LoggerFactory.getLogger(ErrorFallbackFactory.class);
@Override
public DemoFeignClient create(Throwable throwable) {
return new DemoFeignClient() {
@Override
public String hello() {
//如果在create()中打印錯誤信息的話,在應(yīng)用程序啟動時就會打印
ErrorFallbackFactory.LOGGER.info("fall back cause: ", throwable);
return "Error!";
}
};
}
}
4.如果不想某個Feign Client使用Hystrix的話渡嚣,可以使用如下配置:
@FeignClient(name = "eureka-client-demo", configuration = DisableHystrix.class)
public interface DemoFeignClient {
@GetMapping("/hello")
public String hello();
}
@Configuration
public class DisableHystrix {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
3 Hystrix監(jiān)控
3.1 Ribbon中Hystrix的監(jiān)控
Hystrix提供了端點/hystrix.stream
用于監(jiān)控Hystrix的情況梢睛,Ribbon在整合了Hystrix之后肥印,還需要引入Spring Boot 的actuator依賴,才能通過/hystrix.stream
監(jiān)控接口運行情況绝葡。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
/hystrix.stream
的頁面會返回類似下面的監(jiān)控數(shù)據(jù):
data: {"type":"HystrixCommand","name":"hello","group":"Controller","currentTime":1516202320578,"isCircuitBreakerOpen":false,"errorPercentage":100,"errorCount":1,"requestCount":1,"rollingCountBadRequests":0,"rollingCountCollapsedRequests":0,"rollingCountEmit":0,"rollingCountExceptionsThrown":0,"rollingCountFailure":1,"rollingCountFallbackEmit":0,"rollingCountFallbackFailure":0,"rollingCountFallbackMissing":0,"rollingCountFallbackRejection":0,"rollingCountFallbackSuccess":1,"rollingCountResponsesFromCache":0,"rollingCountSemaphoreRejected":0,"rollingCountShortCircuited":0,"rollingCountSuccess":0,"rollingCountThreadPoolRejected":0,"rollingCountTimeout":0,"currentConcurrentExecutionCount":0,"rollingMaxConcurrentExecutionCount":0,"latencyExecute_mean":0,"latencyExecute":{"0":0,"25":0,"50":0,"75":0,"90":0,"95":0,"99":0,"99.5":0,"100":0},"latencyTotal_mean":0,"latencyTotal":{"0":0,"25":0,"50":0,"75":0,"90":0,"95":0,"99":0,"99.5":0,"100":0},"propertyValue_circuitBreakerRequestVolumeThreshold":20,"propertyValue_circuitBreakerSleepWindowInMilliseconds":5000,"propertyValue_circuitBreakerErrorThresholdPercentage":50,"propertyValue_circuitBreakerForceOpen":false,"propertyValue_circuitBreakerForceClosed":false,"propertyValue_circuitBreakerEnabled":true,"propertyValue_executionIsolationStrategy":"THREAD","propertyValue_executionIsolationThreadTimeoutInMilliseconds":1000,"propertyValue_executionTimeoutInMilliseconds":1000,"propertyValue_executionIsolationThreadInterruptOnTimeout":true,"propertyValue_executionIsolationThreadPoolKeyOverride":null,"propertyValue_executionIsolationSemaphoreMaxConcurrentRequests":10,"propertyValue_fallbackIsolationSemaphoreMaxConcurrentRequests":10,"propertyValue_metricsRollingStatisticalWindowInMilliseconds":10000,"propertyValue_requestCacheEnabled":true,"propertyValue_requestLogEnabled":true,"reportingHosts":1,"threadPool":"Controller"}
3.2 Feign中Hystrix的監(jiān)控
1.雖然Feign整合了Hystrix竖独,但是并沒有整合到監(jiān)控的模塊,所以我們需要重新引入依賴包:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.在啟動類添加@EnableCircuitBreaker
或者@EnableHystrix
注解
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class FeignDemoApplication {
public static void main(String[] args) {
SpringApplication.run(FeignDemoApplication.class, args);
}
}
然后就可以通過端點/hystrix.stream
查看監(jiān)控數(shù)據(jù)挤牛。
4 可視化監(jiān)控
4.1 監(jiān)控單個服務(wù)
可以使用hystrix-dashboard進行可視化監(jiān)控:
1.創(chuàng)建一個新項目,并引入以下依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>
- 在啟動類加上
@EnableHystrixDashboard
注解
@EnableHystrixDashboard
@SpringBootApplication
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}
3.啟動應(yīng)用种蘸,打開/hystrix/
端點墓赴,可以看到一下頁面:
往url欄輸入
/hystrix.stream
的鏈接,如:http://localhost:8004/hystrix.stream航瞭,再點擊Monitor Stream按鈕诫硕,就可以看到如下圖的頁面:4.2 監(jiān)控多個服務(wù)
上面的方法只能監(jiān)控單個服務(wù),如果要監(jiān)控多個服務(wù)刊侯,可以使用turbine章办,然后再使用hystrix-dashboard進行進行可視化監(jiān)控。
1.新建一個項目滨彻,引入turbine的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
2.在啟動類添加@EnableTurbine
注解
@EnableTurbine
@SpringBootApplication
public class TurbineApplication {
public static void main(String[] args) {
SpringApplication.run(TurbineApplication.class, args);
}
}
3.配置文件:
server:
port: 8006
spring:
application:
name: turbine
eureka:
client:
service-url:
defaultZone: http://localhost:8001/eureka/
instance:
prefer-ip-address: true
turbine:
app-config: feign-demo,ribbon-demo
cluster-name-expression: "'default'"
combine-host-port: true
- app-config 指定需要監(jiān)控的服務(wù)藕届,用逗號分隔
- cluster-name-expression 指定集群名稱
- combine-host-port 按主機名和端口區(qū)分服務(wù),turbine默認相同host的為同一服務(wù)亭饵,將該屬性設(shè)為true后就可以按主機名和端口區(qū)分服務(wù)
4.啟動應(yīng)用休偶,打開/turbine.stream
端點即可以看到兩者的監(jiān)控數(shù)據(jù)。這個時候辜羊,再將turbine的監(jiān)控數(shù)據(jù)接入hystrix-dashboard踏兜,比如,將url地址http://localhost:8006/turbine.stream填入dash-board的url一欄八秃,再點擊Monitor Stream按鈕碱妆,就可以同時看到兩個服務(wù)的監(jiān)控數(shù)據(jù)。
4.3 使用消息中間件收集數(shù)據(jù)(RabbitMQ)
- 提供服務(wù)的微服務(wù)添加以下依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
- 添加RabbitMQ的配置:
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
- Turbine項目移除turbine的依賴并添加以下依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine-stream</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
- 啟動類中
@EnableTurbine
修改為@EnableTurbineStream
- 添加RabbitMQ的配置昔驱,同2疹尾,同時去掉turbine的配置。