Hystrix:英文意思豪猪,全身是刺,是一种保护机制,是Netflix开源的一个延迟和容错库,用于隔离访问远程服务,防止出现级联失败。如微服务中,一个请求,可能需要调用多个微服务的接口才能实现。如果此时,某个服务出现异常(阻塞情况),用户就不会得到响应,则tomcat的这个线程就不会被释放,而越来越多的用户请求到来,越来越多的线程会阻塞,但服务器支持的线程和并发数是有限的,请求一直阻塞,就会导致服务器资源耗尽。例子:
如工厂生产汽车,如果工厂中一直缺少某个零件,那么这台车就不能完成组装,会处于等待状态,一直到这零件到位。如果此时有很多工人在组装的车都需要这个零件,那么整个工厂都会处于等待状态,工厂生产就会瘫痪。
Hystrix解决雪崩问题的手段有2个:
1,线程隔离
2,服务熔断
线程隔离,服务降级的原理:
Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满,并不会影响到其他服务,调用将被立即拒绝,默认不采用排队,加速失败判定时间。
用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问。如果线程池已满,或者请求超时,则会进行降级处理。用户请求的服务出现故障是不会被阻塞,更不会一直处于等待或者看到系统崩溃消息,系统会给用户返回一个友好的提示结果,如“”“此时服务器繁忙”等等。
什么是服务降级?
优先保证核心服务,而非核心服务不可用或弱可用。例子:如淘宝,双11活动的时候,可以先把不重要的服务停止了,如关闭淘宝直播等,保证核心服务双11活动正常运行。
触发Hystrix服务的主要条件:
1,线程池满了
2,访问超时
下面以consumer-demo、products-service、Eureka-server前面的例子,再记录一下Hystrix,一般是服务的消费方做服务的降级处理。(触发Hystrix:访问超时)
1,consumer-demo引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2,启动类上加注解@EnableCircuitBreaker
//@SpringBootApplication
//@EnableDiscoveryClient
//@EnableCircuitBreaker //服务的熔断
@SpringCloudApplication //包含上三个注解,所有配置这个注解可替代以上三个
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
@Bean
@LoadBalanced //负载均衡,加该注解所有的RestTemplate请求会被LoadBanlancerInterceptor拦截
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
3,编写降级逻辑
3.1,方式1,服务降级写在方法上。
@RestController
@RequestMapping("/products")
//方式1,服务降级写在方法上。
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping(value="/{id}")
@HystrixCommand(fallbackMethod = "queryFallback")//开启失败处理的标志
//请求成功的执行方法
public String queryByid(@PathVariable("id")String id){
//负载均衡
String url="http://products-service/products/"+id;
String p = restTemplate.getForObject(url, String.class);
return p;
}
//三,编写降级逻辑
//熔断降级的逻辑的返回值要和原来的方法逻辑保持一致。如果在方法上,那参数也要一致。
//请求失败的执行方法
public String queryFallback(String id){
return "对不起,访问服务超时,请稍后再试";
}
}
3.2,方式2,服务降级写在类上。
@RestController
@RequestMapping("/products")
//方式2,服务降级写在类上,公用一个。
@DefaultProperties(defaultFallback = "defalutQueryFallback")//一旦降级,就会找到queryFallback方法。
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping(value="/{id}")
//请求成功的信息
//开启失败处理的标志
/* @HystrixCommand(commandProperties ={@HystrixProperty(
name="execution.isolation.thread.timeoutInMilliseconds",value="5000" //局部设置超时
)} )*/
@HystrixCommand //声明熔断的方法
public String queryByid(@PathVariable("id")String id){
//负载均衡
String url="http://products-service/products/"+id;
String p = restTemplate.getForObject(url, String.class);
return p;
}
//三,编写降级逻辑
//熔断降级的逻辑的返回值要和原来的方法逻辑保持一致。如果在方法上,那参数也要一致。
//请求失败的执行方法
public String defalutQueryFallback(){//不能写参数了,因为写在类上公用的方法,参数都是不一样的。
return "对不起,访问服务超时,请稍后再试";
}
}
4,测试 , 模拟访问超时,在提供服务方设置Thread.sleep(),超时后走失败执行的方法queryFallback。(也可把服务提供者的程序停止测试)
@Service
public class ProductsService {
@Autowired
private ProductsMapper productsMapper;
public Products queryById(String pid){
//Thread.sleep(),Hystrix测试模拟超时
try {
Thread.sleep(2000L);//Hystrix默认大于等于1s超时。可配置
} catch (InterruptedException e) {
e.printStackTrace();
}
return productsMapper.selectByPrimaryKey(pid);
}
}
测试结果截图:
5,配置超时时长。可在配置文件中配置,也可在类方法上配置。
找到
类方法上配置超时时间:
//开启失败处理的标志
@HystrixCommand(commandProperties ={@HystrixProperty(
name="execution.isolation.thread.timeoutInMilliseconds",value="5000" //局部设置超时
)} )
public String queryByid(@PathVariable("id")String id){
//负载均衡
String url="http://products-service/products/"+id;
String p = restTemplate.getForObject(url, String.class);
return p;
}
.yml配置文件配置:
#配置全局熔断超时时间。
hystrix:
command:
default: #配置默认全局属性
execution:
isolation:
thread:
timeoutInMilliseconds: 5000
#配置局部熔断超时时间。也可在方法上写
# products-service: #配置默认局部属性
# execution:
# isolation:
# thread:
# timeoutInMilliseconds: 5000
hystrix小总结:
降级
1,引入hystrix启动器
2,熔断时间,默认1s,6s
3,在引导类上添加一个注解:
4,定义熔断方法:局部(要和被熔断的方法返回值和参数列表一致) 全局(返回值要和被熔断的方法返回值一致,参数列表必须为空)
5,@HystrixCommand(fallbackMethod="局部熔断方法名"):声明被熔断的方法
6, @DefaultProperties(defaultFallback = "全局熔断方法名")熔断
1,close:集合状态,所有请求正常方法
2,open:打开状态,所有请求都无法访问。如果在一定时间,失败的比例不小于50%或者次数不小于20此
3,half open:半开状态,打开状态默认5s休眠期,在休眠期所有请求无法正常访问。过了休眠期会进入半开状态,放部分请求通过