SpringCloud—B站学习—Hystrix断路器
服务雪崩
Hystrix是什么
Hystrix主要的三个功能,当然还有其他功能
Hystrix的重要概念
1.服务降级(fallback):服务器繁忙,请稍后再试,不让客户等待并立刻返回一个友好的提示,fallback
哪些情况会发生降级:
1.程序运行异常
2.超时
3.服务熔断触发服务降级
4.线程池/信号量打满也会出现降级
2.服务熔断(break):类比保险丝,当服务达到最大的服务方问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好的提示
过程(就是保险丝):
服务的降级---》进而熔断---》恢复调用链路
3.服务限流(flowlimit):秒杀高并发等操作,严禁一窝蜂地拥挤,大家排队,一秒钟n个,有序进行
高并发出现卡顿
在一个微服务中,当进行压力测试的时候,如果压力过大,那么两个接口运行速度都会变慢,原因只有一个:
故障原因(无法支持高并发)和导致现象
由于有服务器超时缓慢,宕机等现象出现才会有降级,熔断,限流等技术
解决维度
1.超时导致服务器变慢(转圈圈):超时不再等待,服务方(8001)超时了,调用者(80)不能卡死等待,所以我们要选择服务降级
2.出错(宕机或程序运行出错):出错要有兜底,服务方(8001)宕机了,调用者(80)不能卡死等待,所以我们要选择服务降级
3.如果服务方(8001)是OK的,调用者(80)自己出现了问题或者有自我要求(比如自己的等待时间小于服务提供者),所以要自己处理降级
降级
如何处理降级服务(服务提供者)
1.降级配置:@HystrixCommand
注解标签配置
2.先从服务提供者8001自身找问题
1.设置自身调用时间的峰值,峰值以内正常运行,峰值超过了需要有兜底的方法处理,做服务降级fallback,
8001自己先调用自己 ,先自测通过才能对外暴露服务,要先保证自己是正常的
(1).业务类上启动 @HystrixCommand报异常后如何处理----》一旦调用服务方法失败,并抛出了错误信息之后,
就会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
2.由于新添加一个注解,所以主启动类需要一个新的激活的方法(简称主启动类激活):添加新注解---》@EnableCircuitBreaker
所以说只要是服务不可用了(发生任何错误),
做服务降级,兜底的方案都是paymentInfo_timeoutHandler
这个方法
@Service
public class PaymentService {
/**
* 服务成功运行
*
* @param id
* @return
*/
public String paymentInfo_ok(Integer id){
return "线程池: "+Thread.currentThread().getName()+" paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O哈哈~";
}
/**
* 服务超时
*
* @param id
* @return
*/
//fallbackMethod:表示如果我现在出事了谁帮我兜底
@HystrixCommand(fallbackMethod = "paymentInfo_timeoutHandler",commandProperties = {
//这个线程正常的处理逻辑时间就是5000ms,设置自身调用峰值
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
})
public String paymentInfo_timeout(Integer id){
// int age = 10/0;
try {
TimeUnit.SECONDS.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池: "+Thread.currentThread().getName()+" id: "+id+"\t"+"O(∩_∩)O哈哈~"+" 耗时(秒): ";
}
/**
* paymentInfo_timeout出异常兜底的方法
*
* @param id
* @return
*/
public String paymentInfo_timeoutHandler(Integer id){
return "线程池: "+Thread.currentThread().getName()+" 系统繁忙或者运行报错,请稍后再试,id: "+id+"\t"+"o(╥﹏╥)o";
}
}
如何处理降级服务(消费者)
80订单微服务也可以更好的保护自己,自己也可以一样照葫芦画瓢进行客户端的降级保护
Hystrix服务降级,既可以放在客户端也可以放在服务端,但是一般做fallback降级都放在客户端
@RestController
@Slf4j
public class OrderHystrixController {
@Resource
private PaymentHystrixService paymentHystrixService;
//服务成功运行
@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_ok(@PathVariable("id") Integer id){
String result = paymentHystrixService.paymentInfo_ok(id);
return result;
}
//服务超时
// @GetMapping("/consumer/payment/hystrix/timeout/{id}")
// public String paymentInfo_timeout(@PathVariable("id") Integer id){
// String result = paymentHystrixService.paymentInfo_timeout(id);
// return result;
// }
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
//超时属性
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
})
//@HystrixCommand
public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
{
int age = 10/0;
String result = paymentHystrixService.paymentInfo_timeout(id);
return result;
}
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id)
{
return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
}
}
通过上方(服务者和消费者)的两段代码我们可以发现几个事情
1.异常处理的方法和业务逻辑方法混合在一起,耦合极高
2.每个方法都要有个兜底的,使得代码特别膨胀
3.业务方法和服务降级方法合在一起,特别混乱,不会很爽的
避免代码膨胀,这时候我们可以使用@DefaultProperties
注解
除了个别重要的核心业务有专属的降级
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
//超时属性
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
})
其他的就统一同全局降级,即使@HystrixCommand这个注解但是没有指明方法,那么也统一使用全局变量
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
避免和业务逻辑混在一起
假设服务端死掉了,所以说这次的降级主要是在客户端完成的只需要为Feign客户端定义的接口,添加一个服务降级处理的实现类即可实现解耦
未来要面对的异常:
1.运行
2.超时
3.宕机
这是客户端接口,通过Feign调用服务端接口
@Component
@FeignClient(value = "cloud-provider-hystrix-payment")
public interface PaymentHystrixService {
//服务成功运行,调用cloud-provider-hystrix-payment8001服务的方法
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_ok(@PathVariable("id") Integer id);
//服务超时
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_timeout(@PathVariable("id") Integer id);
}
新建一个类,实现这个接口,统一为接口里面的方法进行异常处理,此时如果服务端宕机了,但是我们做了降级处理,让客户端在服务端不可用的情况时,也会获得提示信息,而不是挂起耗死服务器
@Component
public class PaymentFallbackService implements PaymentHystrixService
{
@Override
public String paymentInfo_ok(Integer id)
{
return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
}
@Override
public String paymentInfo_timeout(Integer id)
{
return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
}
}