学习 SpringCloud 微服务是参考纯洁的微笑博客, 看到他提到股市的熔断我也忍不住吐槽一下, 记得当时实施熔断第一天就熔断了, 现在想想也还是搞笑, 从之前的全民炒股到现在的全民炒房, 都是一个炒字, 问题是现在的房市和之前股市的 5000 点一样, 再加上贸易战, 人口老龄化等因素, 不知道能撑多久, 可能是一悲观主义者, 我是不太乐观.
熔断和家里的保险丝一样, 启动保护作用, 电压过高或过低会导致电器损坏, 保险丝的作用就是当电压异常时直接断掉, 不至于影响其他电器的使用, 而且保险丝也只是一根线, 坏掉也影响不大, 是预防雪崩的一种方法. Redis 里面有雪崩和穿透, SpringCloud 中也有雪崩. A 服务调用 B 服务, B 服务调用 C 服务, C 服务调用 D 服务, 如果 D 服务挂了, 那如果不做保护, C 服务也会挂断, C 挂了 B 也会挂, B 挂了 A 也挂, 这样就会都挂了, 这就需要有一个壮士断腕的勇气, 和习大大的理论是异曲同工之妙. 一旦雪崩那恢复的顺序正好相反, 应该先恢复 D 服务, 再依次恢复 C,B,A. 不然假如先恢复 A, 那 B 还是挂了的, 到时候 A 还是会挂. 下面是比较书面的介绍.
1. 断路器机制
断路器很好理解, 当 Hystrix Command 请求后端服务失败数量超过一定比例(默认 50%), 断路器会切换到开路状态(Open). 这时所有请求会直接失败而不会发送到后端服务. 断路器保持在开路状态一段时间后(默认 5 秒), 自动切换到半开路状态(HALF-OPEN). 这时会判断下一次请求的返回情况, 如果请求成功, 断路器切回闭路状态(CLOSED), 否则重新切换到开路状态(OPEN). Hystrix 的断路器就像我们家庭电路中的保险丝, 一旦后端服务不可用, 断路器会直接切断请求链, 避免发送大量无效请求影响系统吞吐量, 并且断路器有自我检测并恢复的能力.
2.Fallback
Fallback 相当于是降级操作. 对于查询操作, 我们可以实现一个 fallback 方法, 当请求后端服务出现异常的时候, 可以使用 fallback 方法返回的值. fallback 方法的返回值一般是设置的默认值或者来自缓存.
3. 资源隔离
在 Hystrix 中, 主要通过线程池来实现资源隔离. 通常在使用的时候我们会根据调用的远程服务划分出多个线程池. 例如调用产品服务的 Command 放入 A 线程池, 调用账户服务的 Command 放入 B 线程池. 这样做的主要优点是运行环境被隔离开了. 这样就算调用服务的代码存在 bug 或者由于其他原因导致自己所在线程池被耗尽时, 不会对系统的其他服务造成影响. 但是带来的代价就是维护多个线程池会对系统带来额外的性能开销. 如果是对性能有严格要求而且确信自己调用服务的客户端代码不会出问题的话, 可以使用 Hystrix 的信号模式 (Semaphores) 来隔离资源.
在 SpringCloud 中实现也比较简单, Feign 中已经依赖了 Hystrix 所以在 maven 配置上不用做任何改动, 只需要三步即可.
1. 配置文件
在上一博客的 EurekaConsumer 基础上, 在属性文件中启动 fegin 的 Hystrix 功能.
feign.hystrix.enabled=true
2. 创建回调类
- package com.example.demo;
- import org.springframework.stereotype.Component;
- import org.springframework.web.bind.annotation.RequestParam;
- @Component
- public class HelloRemoteHystrix implements HelloRemote {
- @Override
- public String hello(@RequestParam(value = "name") String name) {
- return "hello" +name+", this messge send by Hystrix";
- }
- }
3. 添加 fallback 属性
在 HelloRemote 类添加指定 fallback 类, 在服务熔断的时候返回 fallback 类中的内容.
- package com.example.demo;
- import org.springframework.cloud.openfeign.FeignClient;
- import org.springframework.Web.bind.annotation.RequestMapping;
- import org.springframework.Web.bind.annotation.RequestParam;
- @FeignClient(name= "spring-cloud-producer",fallback = HelloRemoteHystrix.class)
- public interface HelloRemote {
- @RequestMapping(value = "/hello")
- public String hello(@RequestParam(value = "name") String name);
- }
此时已完成引入熔断器, 我们可以测试下. 依次启动服务 EurekaServer, 生产者 EurekaClient, 消费者 EurekaConsumer.
此时输入 http://localhost:9001/hello?name=cuiyw 时, 输出正常如下:
当 EurekaClient 停止时, 再次输入 http://localhost:9001/hello?name=cuiyw , 输出如下, 返回的是上面加的熔断 fallback 类, 说明熔断成功.
参考: http://www.ityouknow.com/springcloud/2017/05/16/springcloud-hystrix.html
来源: https://www.cnblogs.com/5ishare/p/11184512.html