Hystrix 提供了熔断、隔离、Fallback、cache、监控等功能,能够在一个、或多个依赖同时出现问题时保证系统依然可用。
一 熔断
断路器
失败次数达到阈值后, 断路器会切换到开路状态。 所有请求快速失败返回备选响应。 熔断时间窗后, 自动切换到半开路状态。判断下次请求,如果请求成功, 断路器关闭,否则重新开路。
容错计数
- Hystrix的Metrics中保存了当前服务的健康状况, 包括服务调用总次数和服务调用失败次数等
- 根据Metrics的计数, 熔断器从而能计算出当前服务的调用失败率, 用来和设定的阈值比较从而决定熔断器的状态切换逻辑
Fallback
Fallback相当于是降级操作。服务不可用时,可返回一个缺省值或缓存的值。
设置熔断
spring-cloud.version:Finchley
RestTemplate调用
- pom
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!--配合dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 启动类注解
@EnableCircuitBreaker //或@EnableHystrix
@SpringBootApplication
- 调用Fallback
在方法上加上@HystrixCommand,并指定fallbackMethod方法。
@HystrixCommand注解的ignoreException参数可以设置忽略的异常
@Autowired
RestTemplate restTemplate;
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@HystrixCommand(fallbackMethod = "fallback")
public String consumer() {
return restTemplate.getForObject("http://localhost:8888/consumer", String.class);
}
public String fallback() {
return "fallback";
}
- 配置url
如果是springboot 2.x则需要配置ServletRegistrationBean, 因为springboot的默认路径不是 “/hystrix.stream”
@Configuration
public class ServletRegistrationConfig {
@Bean
public ServletRegistrationBean registerTurbineBean(){
return new ServletRegistrationBean(new HystrixMetricsStreamServlet(), "/hystrix.stream");
}
}
Feign调用
基于Feign:注解中加上fallback的指定类
- pom
<!--feign包含hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--支持之后的dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 启动类注解
@EnableFeignClients
@SpringBootApplication
- 配置项 开启hystrix,默认关闭
feign.hystrix.enabled=true
- Feign接口fallback
@Component
@FeignClient(name= "spring-cloud-provider",fallback = ConsumerFallback.class,url = "http://localhost:8761/")
public interface ConsumerClient {
@RequestMapping(value = "/consumer", method = RequestMethod.GET)
String consumer();
}
- fallback类
@Component
public class ConsumerFallback implements ConsumerClient{
@Override
public String consumer() {
return "Feign客户端访问失败";
}
}
- 使用Feign服务
@RestController
public class DcController {
@Autowired
ConsumerClient consumerClient;
@GetMapping("/consumer")
public String index() {
return consumerClient.consumer();
}
}
如是springboot 2.x也需配置"/hystrix.stream"
二 监控
spring-cloud.version:Finchley
a.调用hystrix:http://localhost:8002/consumer
b.查看hystrix详情:http://localhost:8002/hystrix.stream
c.查看turbine详情:http://localhost:8001/turbine.stream
单点监控-Dashboard
使用Hystrix Dashboard, 监控单个应用内的服务信息
- pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 启动类 启动类添加启用Hystrix Dashboard
@SpringBootApplication
@EnableHystrixDashboard
访问http://localhost:8080/hystrix监控首页
通过URLhttp://hystrix-app:port/hystrix.stream开启,实现对具体某个服务实例的监控。
多点监控-Turbine
把多个hystrix.stream的内容聚合为一个数据源供Dashboard展示
Spring Cloud Turbine
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 启动类
@EnableTurbine
@SpringBootApplication
- application.properties
spring.application.name=hystrix-dashboard-turbine
server.port=8001
//配置Eureka中的serviceId列表,表明监控哪些服务
turbine.appConfig=node01,node02
//指定聚合哪些集群,多个使用”,”分割,默认为default。
turbine.aggregator.clusterConfig= default
//指定集群名称
turbine.clusterNameExpression= new String("default")
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
在dashboard中查看turbine详情:http://localhost:8001/turbine.stream
Netflix Turbine
使用原生turbine-core可不用eureka
- pom
<dependency>
<groupId>com.netflix.turbine</groupId>
<artifactId>turbine-core</artifactId>
<version>1.0.0</version>
</dependency>
- config.properties 详细见官方文档
#集群名
turbine.aggregator.clusterConfig=${clusterName}
#集群名匹配
turbine.clusterNameExpression= new String("${clusterName}")
#集群url后缀
turbine.instanceUrlSuffix.${clusterName}= /hystrix.stream
#集群实例
turbine.ConfigPropertyBasedDiscovery.${clusterName}.instances= 10.0.64.166:9001,10.0.64.166:9002
- 配置url
@Configuration
public class ServletRegistrationConfig {
@Bean
public ServletRegistrationBean registerTurbineBean(){
return new ServletRegistrationBean(new TurbineStreamServlet(), "/turbine.stream");
}
}
- 启动类
TurbineInit.init();
在Dashboard中查看,Dashboard和Turbine可以建在同一项目
三 其他
资源隔离
采用线程/信号的方式,通过隔离限制依赖的并发量和阻塞扩散。
- 线程隔离 即将每个依赖服务分配独立的线程池进行资源隔离,从而避免服务雪崩。
- 信号隔离 用于限制并发访问,防止阻塞扩散,执行依赖代码的线程依然是请求线程(需通过信号申请)。如果客户端是可信的且可以快速返回,可以使用信号隔离替换线程隔离,降低开销
请求缓存
通过注解开启缓存,和缓存相关的注解一共有三个
- @CacheResult:给该方法开启缓存,默认情况下方法的所有参数都将作为缓存的key
- @CacheKey:指定缓存的key
- @CacheRemove:指定缓存失效commandKey
请求合并
在test10方法上添加@HystrixCollapser注解实现请求合并,用batchMethod属性指明请求合并后的处理方法,collapserProperties属性指定其他属性。
@HystrixCollapser(batchMethod = "test11",collapserProperties = {@HystrixProperty(name ="timerDelayInMilliseconds",value = "100")})
public Future<Book> test10(Long id) {
return null;
}
@HystrixCommand
public List<Book> test11(List<Long> ids) {
System.out.println("test9---------"+ids+"Thread.currentThread().getName():" + Thread.currentThread().getName());
Book[] books = restTemplate.getForObject("http://HELLO-SERVICE/getbook6?ids={1}", Book[].class, StringUtils.join(ids, ","));
return Arrays.asList(books);
}