一、Hystrix之全局服务降级DefaultProperties(DefaultFallback)
1、为什么要有全局服务降级?
有上一篇我们可知,我们在业务类OrderController中为需要降级的服务配置了一个服务降级处理方法,但是当业务方法很多的时候,为每个方法单独配置一个降级方法,显然很傻X,代码必然要膨胀!
没有配置过的就找全局通用的Defalut,单独配置的就使用自己专门配置的降级方法;
DefaultProperties(DefaultFallback = “ ”)
1:1每个方法配置一个降级方法,技术上可行,实际上是傻X;
1:N除了个别重要的核心业务有专属,其他的普通的可以通过DefaultProperties(DefaultFallback = “ ”)统一跳转到统一处理页面
通用和独享的各自分开,避免了代码膨胀,合理减少了代码量!
2、修改OrderController:
@RestController @Slf4j @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod") public class OrderHystrixController { @Autowired private PaymentHystrixService paymentHystrixService; @GetMapping(value = "/consumer/payment/hystrix/ok/{id}") public String paymentInfo_OK(@PathVariable("id") Integer id){ return paymentHystrixService.paymentInfo_OK(id); } @GetMapping(value = "/consumer/payment/hystrix/timeout/{id}") @HystrixCommand public String paymentInfo_TimeOut(@PathVariable("id") Integer id){ return paymentHystrixService.paymentInfo_TimeOut(id); } public String paymentInfo_TimeOutHandler(Integer id){ return "我是消费者Order80,对方Payment8001系统繁忙,请10秒钟后再试 o(╥﹏╥)o"; } public String payment_Global_FallbackMethod(){ return "Global降级处理信息,请稍后再试 o(╥﹏╥)o"; } }
3、启动测试:
可见全局服务降级 DefaultProperties(DefaultFallback) 奏效;
二、Hystrix之通配服务降级FeignFallback
1、在现有PaymentHystrixService接口的基础上,新建一个类PaymentFallbackService实现上面的接口:
@Service public class PaymentFallbackService implements PaymentHystrixService { @Override public String paymentInfo_OK(Integer id) { return "------PaymentFallbackService-paymentInfo_OK o(╥﹏╥)o---"; } @Override public String paymentInfo_TimeOut(Integer id) { //如果失败就会进入方法体,实现服务降级 return "------PaymentFallbackService-paymentInfo_TimeOut o(╥﹏╥)o---"; } }
2、在@FeignClient接口上配置服务降级的实现类:
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackService.class)
3、启动测试:
先正常访问:
在将Payment8001停止,模拟宕机:
显然FeignFallback实现了在@Feign接口上的服务降级!
三、服务熔断Break
服务熔断比服务降级严重——服务熔断必定触发服务降级——可视为更严重的服务降级
1、熔断机制概述:
熔断机制是应对雪崩效应的一种微服务链路保护机制。
当扇出链路的某个微服务出错不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息!
当检测到该节点微服务调用响应正常后,恢复调用链路!
在spring cloud框架里,熔断机制是通过Hystrix实现的,Hystrix会监控微服务间调用的状况;
当失败的调用到一定的阈值后,缺省是5秒内20次调用失败,机会启动熔断机制,熔断机制的注解还是 @HystrixCommand
2、熔断器原理图:
四、服务熔断实战
1、在服务提供者Payment8001的处理类PaymentService中增加一个服务熔断方法paymentCircuitBreaker:
@Service public class PaymentService { //服务熔断 @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", 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") //失败率达到多少后跳闸 }) //**上面的翻译:在10秒钟的时间窗口期中,有10次请求,其他60%即6次是失败的,则断路器跳闸** public String paymentCircuitBreaker(@PathVariable("id") Integer id){ if (id < 0){ throw new RuntimeException("*****id不能为负数"); } String serialNumber = IdUtil.simpleUUID(); return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber; } public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){ return "id不能为负数,请稍后再试 o(╥﹏╥)o id为:" + id; } }
commandProperties 中的大量配置,如何获知?——HystrixCommandProperties类
其中还记载着对应的默认值:
官网:
2、在PaymentController中增加一个调用方法:
@RestController @Slf4j public class PaymentController { @Autowired private PaymentService paymentService; //服务熔断 @GetMapping("/payment/circuit/{id}") public String paymentCircuitBreaker(@PathVariable("id") Integer id){ String result = paymentService.paymentCircuitBreaker(id); log.info("****result:" + result); return result; } }
3、启动Payment8001服务,进行测试:
http://localhost:8001/payment/circuit/1 id为正数时,一切正常,调用成功!
http://localhost:8001/payment/circuit/-1 id为负数时,爆出异常后,进入服务降级方法
但是注意,此时只是正常的服务降级而已!还没触发断路器!!!
4、现在我们要人工触发断路器跳闸,注意:
id为-1时为失败,我们不停地点击,然后断路器跳闸后,迅速地访问id为1的情况,此时即使id为1,也无法访问,因为链路已经跳闸断开了!
过了一会儿,当断路器恢复Closed后,id为1时,又可以访问了:
即,Hystrix断路器 检测到该节点微服务调用响应正常后,恢复调用链路!
5、Hystrix熔断器总结:
熔断类型:
-
熔断关闭Closed:闭合状态,链路调用正常
-
熔断打开Open:请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态(Half Open)
-
熔断半开Half Open:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,熔断器闭合,链路调用恢复正常
6、一张官网的熔断器详细流程图镇楼:
熔断器涉及到的三个重要参数:
快照时间窗口(默认为最近的10秒)、请求总数阈值(默认为20次)、错误百分比阈值(默认为50%)
即默认断路器跳闸条件是: 在最近的10秒类,有20次请求,且其中50%,即10次以上失败,才会熔断!
7、熔断器跳闸后发生的事?
再有请求调用的时候,将不会调用主逻辑,而是直接调用降级fallback方法,通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延时的效果!
8、原来的主逻辑要如何恢复?
对于这一问题,Hystrix也为我们实现了自动恢复功能:
当断路器打开,对主逻辑进行熔断之后,hystrix会启动一个休眠时间窗口,在这个时间窗口内,降级逻辑临时地成为了主逻辑;
当休眠时间窗口到期后,断路器将进入半开状态,释放一次请求到原来的主逻辑上,如果此次请求正常返回,那么断路器将闭合,主逻辑恢复;
如果这次请求依然有问题,断路器继续进入断开状态,休眠时间窗口重新开始计时!!!
七、Hystrix图形化Dashboard的搭建
1、除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求执行信息,并以统计报表和图形化的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等。
Netflix通过hystrix-metrics-event-stream项目实现了对以上指标的监控。Spring Cloud也提供了Hystrix Dashboard的整合,将监控内容转化成可视化界面。
2、Hystrix Dashboard监控项目搭建——项目cloud-consumer-hystrix-dashboard9001
pom.xml中核心依赖:
<dependencies> <!--Hystrix 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> <!--热部署devtools--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies>
3、application.yml配置文件:
server: port: 9001
4、主启动类:HystirxDashboardMain9001.java:
@SpringBootApplication @EnableHystrixDashboard public class HystrixDashboardMain9001 { public static void main(String[] args) { SpringApplication.run(HystrixDashboardMain9001.class, args); } }
5、启动项目,访问: localhost:9001/hystrix ,当看到如下界面,说明我们的Dashboard服务已经搭建完成;
八、Hystrix图形化Dashboard的使用
1、如果某个项目需要被Hystrix Dashboard除了要引入actuator依赖外,还必须要做另一件事:
需要在主启动类中增加以下Bean注入,这是Springcloud升级后的坑:
以项目HystrixPayment8001为例:
@SpringBootApplication @EnableEurekaClient @EnableCircuitBreaker public class PaymentHystrixMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentHystrixMain8001.class, args); } /** * 此配置是为了服务监控而配置,与服务容错本身无关,springcloud升级后的坑; * ServletRegistrationBean 是因为springboot的默认路径不是“/hystrix.stream”; * 只要在自己的项目里配置上此配置Bean注入即可; * @return */ @Bean public ServletRegistrationBean getServlet(){ HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet); registrationBean.setLoadOnStartup(1); registrationBean.addUrlMappings("/hystrix.stream"); registrationBean.setName("HystrixMetricsStreamServlet"); return registrationBean; } }
2、之后启动项目,以下面的方式配置所要监控的 payment8001项目:
3、在点击Monitor Stream为了看到监控效果,我们先多访问几次以下路径,分别对这种正常访问和不正常访问:
http://localhost:8001/payment/circuit/1
http://localhost:8001/payment/circuit/1
以上图中的几处:
-
7色:不同的颜色对应着不同的请求状态,上图有明确解释
-
1圈——实心圈:两层含义:
-
颜色:代表实例的健康程度: 绿色 > 黄色 > 橙色 > 红色
-
大小:大小会根据实例的请求流量发生变化,流量越大,实心圆越大;
-
1线:用来记录2分钟内的流量的相对变化,可以通过它来观察到流量的上升和下降趋势;
所以,通过该实心圆的展示就可以在大量的实例中快速地发现 故障实例和高压力实例!
4、整图详细说明:
5、更详细的图解:
6、最终,我们实际生产中,服务监控模板可能就是这个样子:
到了这里,Hystrix的内容就差不多结束了,关于服务限流,在学习 Sentinel 的时候一并学习;
Hystrix Dashboard有一点不好就是还需要我们自己去搭建服务监控平台,等到时候Sentinel的时候,就不需要自己搭建了,Sentinel提供了自己的服务监控界面,直接网址访问!
个人此项目代码地址(持续更新):