转载请注明作者及出处:
作者:银河架构师
熔断降级
微服务架构中,一般把一个大型的单个应用程序和服务拆分为数个甚至数十个的支持微服务,为了保证高可用,每个微服务都可能会部署集群。
即便如此,也无法保证100%可用。如遇程序问题、网络问题、不可抗拒因素等造成的服务不可用,调用此服务就会发生堵塞。
此时再加上外部高并发带来的大量请求,由于服务与服务之间的互相依赖,一瞬间就能引起整个微服务系统的瘫痪,也称之为“雪崩”效应。
为了解决此问题,“断路器”应运而生。
服务熔断
服务熔断类似于电路中的保险装置,当电路负荷过大,会自动烧毁,以保护整个电路安全。服务熔断也是一样的道理,当服务出现不可用或响应超时的情况时,为防止整个系统出现雪崩,会暂停会当前服务的调用。
服务降级
服务降级会针对服务状态及整个系统的负荷情况作出考量,如服务不可用,或者对某些服务负荷会比较高,为了预防某些业务场景出现不可用、负荷过载、响应过慢的情况,在内部暂时舍弃一些非核心请求,直接返回一个预先设置好的fallback默认结果。
如此一来,虽然有损且舍弃了部分用户体验,但毕竟最终保证了整个系统的稳定性和可用性。
简介
Netflix has created a library called Hystrix that implements the circuit breaker pattern. In a microservice architecture it is common to have multiple layers of service calls.
Hystrix实现并开源了断路器组件Hystrix,而Spring Cloud针对Netflix开源的Hystrix组件,封装了基于Spring Cloud的断路器组件。
在微服务架构中,通常有多个服务调用层。
(来源于Spring官网)
较低级别的服务中出现的服务故障可能会导致连锁故障,当对特定服务的调用达到某个阈值时(Hystrix中默认在5秒钟内出现20次故障),断路器将会打开且不会再对此服务进行调用。
(来源于Spring官网)
断路器打开后,可避免连锁故障,fallback方法可以直接返回特定值。
准备工作
本文基于之前服务消费者(rest+ribbon)、服务消费者(feign)文章工程,启动xmall-product工程,端口为8080。
添加断路器
分别在xmall-product-clients-ribbon、xmall-product-clients-feign工程pom文件中添加hystrix依赖。
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
ribbon方式
基于xmall-product-clients-ribbon进行断路器相关改造。
开启hystrix
程序启动类XmallProductClientsRibbonApplication中添加@EnableHystrix注解开启hystrix。
package com.luas.xmall.product.clients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.hystrix.EnableHystrix; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableHystrix @SpringBootApplication public class XmallProductClientsRibbonApplication { public static void main(String[] args) { SpringApplication.run(XmallProductClientsRibbonApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
改造SkuService
添加fallback方法,在方法上添加@HystrixCommand开启熔断功能,并声明fallback方法。fallback方法在服务不可用时,返回默认商品信息。
package com.luas.xmall.product.clients.clients; import cn.hutool.core.map.MapUtil; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @Component public class SkuService { @Autowired private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "infoFallback") public Object info(String skuId) { return this.restTemplate.getForObject("http://xmall-product/sku/{skuId}", Object.class, skuId); } private Object infoFallback(String skuId) { return MapUtil.builder() .put("skuId", "0000000") .put("name", "未知") .put("price", "99999") .put("port", "未知") .build(); } }
验证
正常访问http://localhost:8082/sku/1122,返回商品1122的信息。
停止xmall-product服务,再次访问http://localhost:8082/sku/1122,返回默认商品信息。
此时说明,当xmall-product不可用时,通过ribbon调用此服务会执行降级策略,快速失败并返回预先设置好的默认信息,而不是等待服务调用超时,导致调用堵塞。
feign方式
基于xmall-product-clients-feign进行断路器相关改造。
开启hystrix
feign自带熔断器功能,Spring Cloud在D版本之后,默认关闭feign的熔断功能,需要手工打开。
feign:
hystrix:
enabled: true
改造SkuService
添加SkuFallbackService,在xmall-product服务不可用时,返回默认商品信息。
package com.luas.xmall.product.clients.clients; import cn.hutool.core.map.MapUtil; import org.springframework.stereotype.Component; @Component public class SkuFallbackService implements SkuService { @Override public Object info(String skuId) { return MapUtil.builder() .put("skuId", "0000000") .put("name", "未知") .put("price", "99999") .put("port", "未知") .build(); } }
在@FeignClient注解中声明fallback类。
package com.luas.xmall.product.clients.clients; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @FeignClient(name = "xmall-product", fallback = SkuFallbackService.class) public interface SkuService { @RequestMapping(value = "/sku/{skuId}", method = RequestMethod.GET) Object info(@PathVariable("skuId") String skuId); }
验证
正常访问http://localhost:8083/sku/1122,返回商品1122的信息。
停止xmall-product服务,再次访问http://localhost:8083/sku/1122,返回默认商品信息。
同ribbon方式,当xmall-product不可用时,通过feign调用此服务会执行降级策略,快速失败并返回预先设置好的默认信息,而不是等待服务调用超时,导致调用堵塞。
源码
github
https://github.com/liuminglei/SpringCloudLearning/tree/master/06/
gitee
https://gitee.com/xbd521/SpringCloudLearning/tree/master/06/
正文完!
微信搜索【银河架构师】,发现更多精彩。
技术资料领取方法:关注公众号,回复微服务,领取微服务相关电子书;回复MK精讲,领取MK精讲系列电子书;回复JAVA 进阶,领取JAVA进阶知识相关电子书;回复JAVA面试,领取JAVA面试相关电子书,回复JAVA WEB领取JAVA WEB相关电子书。