一、关于
Hystrix是一个延迟和容错库,旨在隔离远程系统、服务和第三方库,防止故障级联,并在故障不可避免的复杂分布式系统中保证弹性。
本文代码仓库地址:https://github.com/lazyrabb1t/rabb-springcloud-demo
二、使用Hystrix
1、首先启动eureka服务端,并注册多个服务提供者,可参照eureka篇,服务提供者添加相关测试方法如下
@RestController
@RequestMapping("/hystrix")
@Slf4j
public class HystrixController {
@GetMapping
public String normal() {
return "hello hystrix!";
}
@GetMapping("/timeout")
public String timeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(5);
return "hello hystrix!";
}
@GetMapping("/exception")
public String exception() {
int i = 10 / 0;
return "hello hystrix!";
}
}
2、创建hystrix模块
3、pom.xml引入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>xyz.lazyrabbit</groupId>
<artifactId>rabb-hystrix</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rabb-hystrix</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
4、application.yml配置
server:
port: 12000
spring:
application:
name: rabb-hystrix
eureka:
client:
service-url:
defaultZone: http://localhost:10002/eureka/
rabb:
service:
test: http://RABB-EUREKA-PROVIDER
5、启动类添加@EnableCircuitBreaker注解
也可以使用@SpringCloudApplication注解,它包含了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker三个注解
6、使用@HystrixCommand
@HystrixCommand中的常用参数:
- fallbackMethod:指定服务降级处理方法;
- ignoreExceptions:忽略某些异常,不发生服务降级;
- commandKey:命令名称,用于区分不同的命令;
- groupKey:分组名称,Hystrix会根据不同的分组来统计命令的告警及仪表盘信息;
- threadPoolKey:线程池名称,用于划分线程池。
@SpringBootApplication
@RestController
@EnableCircuitBreaker
public class HystrixApplication {
@Autowired
RestTemplate restTemplate;
@Value("${rabb.service.test}")
private String testService;
public static void main(String[] args) {
SpringApplication.run(HystrixApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@GetMapping
@HystrixCommand(fallbackMethod = "defaultHello")
public String hello() {
// 正常调用情况
return "hystrix invoke:" + restTemplate.getForObject(testService + "/hystrix", String.class);
}
@GetMapping("timeout")
@HystrixCommand(fallbackMethod = "defaultHello", commandProperties = {
// 设置超时时间
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500")
})
public String timeout() {
// 提供者超时情况
return "hystrix invoke:" + restTemplate.getForObject(testService + "/hystrix/timeout", String.class);
}
@GetMapping("consumer/error")
@HystrixCommand(fallbackMethod = "defaultHello")
public String consumerError() {
// 消费者异常情况
int i = 10 / 0;
return "hystrix invoke:" + restTemplate.getForObject(testService + "/hystrix", String.class);
}
@GetMapping("provider/error")
@HystrixCommand(fallbackMethod = "defaultHello")
public String providerError() {
// 提供者异常情况
return "hystrix invoke:" + restTemplate.getForObject(testService + "/hystrix/exception", String.class);
}
/**
* 默认回调方法
*
* @param throwable
* @return
*/
public String defaultHello(Throwable throwable) {
return throwable == null ? "something wrong!" : "exception:" + throwable.getMessage();
}
}
三、进阶使用
1、缓存
@CacheResult:开启缓存,默认所有参数作为缓存的key,cacheKeyMethod可以通过返回String类型的方法指定key;
@CacheKey:指定缓存的key,可以指定参数或指定参数中的属性值为缓存key,cacheKeyMethod还可以通过返回String类型的方法指定;
@CacheRemove:移除缓存,需要指定commandKey。
2、请求合并
使用@HystrixCollapser可以合并请求
- batchMethod:用于设置请求合并的方法;
- collapserProperties:请求合并属性,用于控制实例属性,有很多;
- timerDelayInMilliseconds:collapserProperties中的属性,用于控制每隔多少时间合并一次请求;
3、服务熔断
使用如下配置,如果在10秒内,失败率达到请求次数(10)的百分之60,也就是6次就会打开断路器;否则断路器依然关闭
当断路器开启时,所有的请求都不会转发,而是直接调用fallback方法;在一段时间后(默认5秒),断路器处于半开状态,尝试将请求转发,如果得到正确的响应。则将断路器关闭,恢复正常调用;否则断路器状态再次打开,重新计时后再进入半开状态
@GetMapping("breaker")
@HystrixCommand(fallbackMethod = "defaultHello", commandProperties = {
// 开启断路器
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
// 请求次数
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
// 时间窗口期
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
// 失败率
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
})
public String breaker() {
log.info("invoke breaker !");
// 提供者异常情况
return "hystrix invoke:" + restTemplate.getForObject(testService + "/hystrix/exception", String.class);
}
4、服务降级与服务熔断
服务熔断指的是目标服务不可用或者请求响应超时时为了保证整体服务可用,不再调用目标服务,而是直接返回默认处理(释放系统资源),通过某种算法检测到目标服务可用后,则恢复其调用。
服务降级指的是当服务器压力剧增时,根据当前业务、流量情况对一些服务(一般为非核心业务)进行有策略的降级,确保核心业务正常执行。即释放非核心服务占用的服务器资源确保核心任务正常执行。
相同点:
- 目标一致:都是从可用性和可靠性出发,为了防止系统崩溃;
- 用户体验类似:最终都让用户体验到的是某些功能暂时不可用;
不同点:
- 触发原因不同:服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
四、Hystrix Dashboard
1、创建hystrix-dashboard模块
2、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
3、application配置
server:
port: 13000
spring:
application:
name: rabb-hystrix-dashboard
eureka:
client:
service-url:
defaultZone: http://localhost:10002/eureka/
hystrix:
dashboard:
proxy-stream-allow-list: "*" # 放行host
4、启动类添加@EnableHystrixDashboard注解
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardApplication.class, args);
}
}
5、修改第一步创建的hystrix模块
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
添加配置
management:
endpoints:
web:
exposure:
include: 'hystrix.stream' #暴露hystrix监控端点
注册bean
@Bean
public ServletRegistrationBean getServlet(){
HystrixMetricsStreamServlet hystrixMetricsStreamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(hystrixMetricsStreamServlet);
servletRegistrationBean.setLoadOnStartup(1);
servletRegistrationBean.setUrlMappings(Arrays.asList("/hystrix.stream"));
servletRegistrationBean.setName("HystrixMetricsStreamServlet");
return servletRegistrationBean;
}
6、启动eureka-server、eureka-provider、hystrix以及hystrix-dashboard模块
7、访问dashboard模块(http://localhost:13000/hystrix)
填写要监控的地址(http://localhost:12000/actuator/hystrix.stream),设置delay以及title
点击monitor stream即可监控相应模块
访问hystrix模块中配置了断路器的接口,然后在dashboard就可以监控相应的接口
8、图表解读
9、Turbine
Hystrix Dashboard 在集群环境下的作用基本上可以忽略,所以需要一种方式来聚合整个集群下的监控状况,Turbine就是用来聚合所有相关的 hystrix.stream 流的解决方案。