背景
在一个复杂的分布式体系中,可能有数十个依赖关系,这些依赖关系在某些时候将不可避免地失败。
服务雪崩:
多个微服务之间调用的时候,服务A调用B,B又调用C,C又调用其他微服务...,在这个链路上某个微服务调用响应时间过长或者不可用,对A地调用会占用越来越多的系统资源,进而引起系统崩溃,所谓地“服务雪崩”。
Hystrix是一个用于处理分布式系统地延迟和容错的开源库,在分布式系统里,许多依赖不可避免地会调用失败(超时、异常)等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免机连故障,以提高分布式系统的弹性。
"断路器"本身是一种开关,当某个服务单元发生故障后,通过断路器的故障监控,向调用方返回一个符合预期、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要的占用,从而避免故障在分布式系统中的蔓延,乃至雪崩。
Hystrix重要概念
服务降级fallback
服务器繁忙,请稍后尝试,不让客户端等待并立即返回一个友好提示,fallback
服务降级情况:
- 程序运行异常
- 超时
- 程序熔断触发服务降级
- 线程池/信号量打满也会导致服务降级
服务熔断break
类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示。
服务降级->熔断->恢复调用链路。
服务限流flowlimit
秒杀高并发等操作,严禁一窝蜂过来拥挤,大家排队,一秒N个,有序进行。
服务端降级初体验
部分依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
Service方法
@Service
public class PaymentService {
/**
* @Author wen.jie
* @Description fallbackMethod中定义了回调方法
* HystrixProperty中定义了超时时间
* @Date 2020/9/6 13:00
**/
@HystrixCommand(fallbackMethod = "paymentInfo_Handler",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String paymentInfoTimeOut(Integer id){
int time = 5;
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:"+Thread.currentThread().getName()+" paymentInfoTimeOut"+":"+id;
}
/**
* @Author wen.jie
* @Description 服务降级的fallback方法
* @Date 2020/9/6 12:58
**/
public String paymentInfo_Handler(Integer id){
return "线程池:"+Thread.currentThread().getName()+" paymentInfoTimeOut"+":"+id+"=====hystrix-handler";
}
}
主启动类上加上@EnableCircuitBreaker
注解或者在主启动类上直接加上@SpringCloudApplication
@EnableCircuitBreaker
@EnableEurekaClient
@SpringBootApplication
public class PaymentHystrixMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrixMain8001.class,args);
}
}
启动服务后,调用此方法,发现三秒后调用了FallBack方法。
全局服务降级
在当前类上标注@DefaultProperties(defaultFallback = "paymentIfo_Global_Handler"),表明当前类的FallBack方法,都去找paymentIfo_Global_Handler方法,然后在需要服务降级的方法上只加上@HystrixConmmand就行了
@RestController
@DefaultProperties(defaultFallback = "paymentIfo_Global_Handler")
public class OrderHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@HystrixCommand
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfoTimeout(@PathVariable Integer id)
{
return paymentHystrixService.paymentInfoTimeout(id);
}
public String paymentIfo_Global_Handler(){
return "线程池:"+Thread.currentThread().getName()+"=====hystrix-handler-order-global";
}
}
运行效果:
但是FallBack混在controller中,有点混乱,且耦合度高。
我们只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。
Feign接口:
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallBackService.class)
public interface PaymentHystrixService {
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfoTimeout(@PathVariable("id") Integer id);
}
服务降级处理的实现类:
@Component
public class PaymentFallBackService implements PaymentHystrixService {
@Override
public String paymentInfoTimeout(Integer id) {
return "PaymentFallBackService--fallback";
}
}
配置yml
feign:
hystrix:
#在feign中开启hystrix
enabled: true
hystrix:
command:
default: #default全局有效,service id指定应用有效
execution:
timeout:
#如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为熔断根据
enabled: true
isolation:
thread:
timeoutInMilliseconds: 3000 #断路器超时时间,默认1000ms