本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
分布式能带来好处,也能带来害处。我们在前面使用 Feign 来调用各个服务系统,当我们调用的服务多了并且出现层级调用的时候,当其中的某一环节出现故障,就会导致调用者出现故障,进而整个故障蔓延到整个系统,导致整个系统都不可用。那么在 Spring Cloud 提供的微服务中是如何处理这种情况的呢?答案就是 Hystrix 断路器。本文将通过一些案例,开启 Feign 的 Hystrix 断路器功能。
CircuitBreaker 有人翻译作断路器,有人翻译作熔断器。其实就是对服务做一个降级保护处理,有兴趣的可以阅读 Martin Fowler 的 Circuit Breaker 一文进行阅读。
从马丁福勒的这篇文章中,我们可以看到某一服务故障,没有断路器的话对整个系统的影响,容易引起雪崩效应。类似与上图,故障蔓延到整个系统,导致整个系统不可用。和我们经常提到的高可用相违背。
Hystrix 的介绍
Hystrix 是 Netflix 开源的微服务套件之一,在微服务领域有广泛的使用。它是由 Java 实现的,用来处理分布式系统发生故障或延迟时的容错库,它提供了断路器、资源隔离、自我修复三大功能。
- 断路器:当 Hystrix 发现在过去某段时间内对服务 AA 的调用出错率达到阀值时,它就会“熔断”该服务,后续任何向服务 AA 的请求都会快速失败,而不是白白让调用线程去等待
- 资源隔离:首先,Hystrix 对每一个依赖服务都配置了一个线程池,对依赖服务的调用会在线程池中执行。比如,服务 AA 的线程池大小为 20,那么 Hystrix 会最多允许有 20 个容器线程调用服务 AA(超出20,它会拒绝并快速失败)。这样即使服务 AA 长时间未响应,容器最多也只能堵塞 20 个线程,剩余的线程仍然可以处理用户请求。
- 自我修复:处于熔断状态的服务,在经过一段时间后,Hystrix 会让其进入“半关闭”状态(即允许少量请求通过),然后统计调用的成功率,若每个请求都能成功,Hystrix 会恢复该服务,从而达到自我修复的效果。
Hystrix 的 Fallback 相当于是降级操作. 对于服务调用, 我们可以实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 fallback 方法返回的数据。
下面我们一起来看一个例子。
首先,我们为了不污染前面教程中写的源码,我们再新建一个工程 xttblog-feign-hystrix。它的 pom.xml 和 xttblog-cloud-consumer 一致。application.yml 略有变化,只开启了熔断器配置:
feign: hystrix: enabled: true
然后,入口类 FeignHystrixApplication 也和 xttblog-cloud-consumer 一样,只是类名发生了变化。Controller 和 Service 都沿用的 xttblog-cloud-consumer 中的代码。我们在编写一个 CalRemoteService 的实现类 CalRemoteHystrixImpl,重写其中的 add 方法,让其在发生熔断后,返回默认值。
@Component public class CalRemoteHystrixImpl implements CalRemoteService{ @Override public String add(@RequestParam(value = "a") Integer a, @RequestParam("b") Integer b) { return "服务熔断,-10086"; } }
最后 CalRemoteService 接口中,我们对 @FeignClient 注解添加一个 fallback 属性,指定发生熔断后,回调的实例。
@FeignClient(name= "xttblog-cloud-producer", fallback = CalRemoteHystrixImpl.class) public interface CalRemoteService { @RequestMapping(value = "/cal/add") public String add(@RequestParam(value = "a") Integer a, @RequestParam("b") Integer b); }
做完上面的编码后,我们依次启动 xttblog-eureka-server、xttblog-cloud-producer、xttblog-feign-hystrix。在浏览器中访问 http://localhost:7788/test/radd?a=1&b=2,返回正确的内容。
然后,我们在手动停掉 xttblog-cloud-producer 服务,再次刷新浏览器,返回的就是我们配置的熔断后的默认值。说明我们的服务进行了成功的熔断。
本文案例源码已全部上传至:https://github.com/xmt1139057136/xttblog-cloud
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!