一、概念部分
1.什么是熔断器?
熔断,就是断开与服务器的连接,熔断器是在服务不可用的时候主动断开,以免造成更多的雪崩效应,他是保护服务高可用的最后一道防线。
2.为什么需要熔断器?
为保证服务高可用,最先想到的是服务集群,但集群并不能完全的保证服务高可用,
当某个服务出现故障时,在负载均衡的时候可能多次被调用到,调用方由于无法得到调用结果,会出现请求超时会其他异常,这时候如果不及时的熔断服务,就有可能会有更多的调用者去调用已经出现故障的服务节点,造成大量调用失败,甚至引发联级故障的雪崩。
在分布式系统中,通常会有很多的服务调用,比如服务调用关系:AB->C->D。
基础服务的故障可能会导致联级故障,如下图所示:
我们需要一个熔断机制,当某个节点出现故障时,及时的做熔断处理,防止更多的服务调用失败。
二、代码实现
服务熔断
1.创建项目consumer-service,在build.gradle中添加依赖
dependencies { compile('org.springframework.cloud:spring-cloud-starter-eureka') compile('org.springframework.cloud:spring-cloud-starter-feign') compile('org.springframework.cloud:spring-cloud-starter-hystrix') compile('org.springframework.cloud:spring-cloud-starter-hystrix-dashboard') compile('org.springframework.boot:spring-boot-starter-actuator') testCompile('org.springframework.boot:spring-boot-starter-test') }
2.创建application.yml
#spring配置spring: application: #应用名称(服务调用者) name: consumer-service#服务器配置server: #端口 port: 7000#配置服务注册发现eureka: client: #配置服务注册中心地址 service-url: defaultZone: https://www.apiboot.cn/eureka#feign远程调用配置feign: hystrix: #开启熔断 enabled: true
3.启动类添加注解
/** * 服务调用者 * @ EnableDiscoveryClient 开启客户端发现 * @ EnableFeignClients 开启Feign远程调用 * @ EnableHystrixDashboard 开启熔断监控仪表盘 * @ EnableCircuitBreaker 开启断路器 */@SpringBootApplication@EnableDiscoveryClient@EnableFeignClients@EnableHystrixDashboard@EnableCircuitBreakerpublic class ConsumerServiceApplication { public static void main(String[] args) { SpringApplication.run(ConsumerServiceApplication.class, args); } }
4.创建远程调用接口 HelloRemote.java
/** * feign远程调用接口 * FeignClient注解的name属性值要写服务提供者在注册中心注册的服务名称 * FeignClient注解的fallback属性值表示远程调用失败时的回调类 */@FeignClient(name = "producer-service",fallback = HelloRemoteFallback.class)public interface HelloRemote { /** * 远程调用方法 * @param name 名称 * @return 远程调用结果 */ @RequestMapping(value = "/hello") String hello(@RequestParam(value = "name") String name); }
5.创建远程调用回调类 HelloRemoteFallback.java
/** * 熔断回调类 * 继承feign远程调用接口,并在实现方法中输出回调的信息 */@Componentpublic class HelloRemoteFallback implements HelloRemote { /** * 远程调用失败,将会回调该方法 * @param name 名称 * @return 自定义返回信息 */ @Override public String hello(@RequestParam(value = "name") String name) { return "hello " + name + ", this message is failed"; } }
6.创建控制器类 HelloController.java
/** * Hello控制器 测试远程调用接口 * 将远程调用接口注入,并调用远程方法 */@RestControllerpublic class HelloController { @Autowired private HelloRemote helloRemote; // 远程调用接口 /** * 输出hello方法 * @param name 名称 * @return 远程调用返回值 */ @RequestMapping(value = "/hello/{name}") public String hello(@PathVariable(value = "name") String name){ return helloRemote.hello(name); } }
7.打包部署到服务器上,访问服务注册中心 https://www.apiboot.cn/
发现我们的服务consumer-service已经成功运行起来并且注册到了服务注册中心,
consumer-service所调用的远程服务 producer-service我也已经提前运行起来了。
为了测试方便,每个应用我都绑定了二级域名,访问我们的服务调用者提供的远程调用方法
https://consumer.apiboot.cn/hello/lanshiqin
我们通过consumer-service服务 远程调用了producer-service服务,并且成功响应。
接下来我们手动停止服务提供者 producer-service服务,假装服务故障。
我们再次访问服务调用者提供的远程调用方法 https://consumer.apiboot.cn/hello/lanshiqin
发现远程调用不成功,但是不会因为调用不成功导致服务异常,而是熔断了远程服务的连接并以友好的方式触发了我们的远程调用失败时指定的本地回调方法,输出了自定义信息。证明熔断成功。
熔断监控
由于我们为服务消费者添加了熔断监控并且开启了服务,所以我们可以监控服务消费者项目 consumer-service 的熔断信息
打开浏览器输入地址: https://consumer.apiboot.cn/hystrix
浏览器返回了刺猬图标的界面,我们可以通过他来监控服务调用的成功率情况。
Hystrix Dashboard 面板的地址栏里输入,点击 Monitor Stream,进入监控的图表页面。
一开始该页面的Circuit页卡会显示Loading…,我们只要访问以下服务消费者的地址 https://consumer.apiboot.cn/hello/lanshiqin 监控面板即可显示熔断信息与图表详情。
下图为服务提供者正常被服务消费者调用的时候的熔断信息
我们把服务提供者服务关闭,让服务消费者无法正常远程调用到服务,然后查看服务消费者的熔断信息,发现100.0%的调用失败,因为我们没有做服务提供者集群,所以唯一的服务提供者被关闭后,远程调用将100%调用失败。
到此,我们的单个应用的熔断监控器已经成功的监控到远程服务的调用情况。
作者:蓝士钦
链接:https://www.jianshu.com/p/e8a477a051d8