在微服务架构中,存在那么多的服务单元,若一个单元出现故障(由于网络原因或者自身原因),就很容易因依赖关系而引发故障的蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构更加不稳定。为了解决这样的问题,产生了断路器等一系列的服务保护机制。(A服务调用B服务,B服务由于自身处理逻辑等原因造成响应缓慢,会导致A服务线程被挂起,以等待B服务执行,在高并发情况下,这些挂起的线程会导致后面调用A服务的请求被阻塞,最终导致A服务也不可用)。

  加入断路器后,当服务不可用时,通过断路器的故障监控,会直接执行回调函数,直接返回一串字符串,而不是等待响应超时,这样就不会使得线程调用故障服务被长时间占用不释放,从而避免了故障在分布式系统中的蔓延。

    本节内容在上节内容基础上,阅读此节之前,先看上节Spring Cloud之Eureka、Ribbon

一、无断路器示例

  启动上节的eureka-server、service-hello(8081/8082)、ribbon-consumer工程

  在未加入断路器之前,关闭8081实例,发送GET请求到http://localhost:9000/ribbon-consumer,轮询8081/8082,当轮询到8081后(因为8081实例被关)会得到下面输出:

二、加入断路器示例

  在ribbon-consumer工程的pom.xml引入下面依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-hystrix</artifactId>
  4. </dependency>

  在ribbon-consumer工程的 主类ConsumerApplication中使用@EnableCircuitBreaker注解开启断路器功能

  1. package com.stonegeek;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  6. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  7. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  8. import org.springframework.context.annotation.Bean;
  9. import org.springframework.web.client.RestTemplate;
  10.  
  11. /**
  12. * Created by StoneGeek on 2018/5/28.
  13. * 博客地址:http://www.cnblogs.com/sxkgeek
  14. */
  15. @EnableCircuitBreaker
  16. @EnableDiscoveryClient
  17. @SpringBootApplication
  18. public class RibbonConsumerApplication {
  19.  
  20. @Bean
  21. @LoadBalanced
  22. RestTemplate restTemplate(){
  23. return new RestTemplate();
  24. }
  25. public static void main(String[] args) {
  26. SpringApplication.run(RibbonConsumerApplication.class, args);
  27. }
  28. }

  改造服务消费方式,新增HelloService类,注入RestTemplate实例,然后将在ConsumerController中对RestTemplate的使用迁移到helloService函数中,最后,在helloService函数上增加@HystrixCommand注解来指定回调方法:

  1. package com.stonegeek.service;
  2.  
  3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.stereotype.Service;
  6. import org.springframework.web.client.RestTemplate;
  7.  
  8. import java.util.logging.Logger;
  9.  
  10. /**
  11. * Created by StoneGeek on 2018/5/29.
  12. * 博客地址:http://www.cnblogs.com/sxkgeek
  13. */
  14. @Service
  15. public class HelloService {
  16. private final Logger logger =Logger.getLogger(String.valueOf(getClass()));
  17. @Autowired
  18. RestTemplate restTemplate;
  19.  
  20. @HystrixCommand(fallbackMethod = "helloFallback")
  21. public String helloService(){
  22. //加logger更清晰的看出执行时间
  23. long start =System.currentTimeMillis();
  24. String result=restTemplate.getForEntity("http://SERVICE-HELLO/hello",String.class).getBody();
  25. long end=System.currentTimeMillis();
  26. logger.info("Spend time:"+(end-start));
  27. return result;
  28. }
  29.  
  30. public String helloFallback(){
  31. return "error";
  32. }
  33.  
  34. }

  修改RibbonConsumerApplication.class

  1. package com.stonegeek.controller;
  2.  
  3. import com.stonegeek.service.HelloService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import org.springframework.web.client.RestTemplate;
  9.  
  10. /**
  11. * Created by StoneGeek on 2018/5/28.
  12. * 博客地址:http://www.cnblogs.com/sxkgeek
  13. */
  14. @RestController
  15. public class ConsumerController {
  16. /**
  17. * @Author: StoneGeek
  18. * @Date: 2018/5/29
  19. * @Description:之前不加断路器代码
  20. */
  21. // @Autowired
  22. // RestTemplate restTemplate;
  23. //
  24. // @RequestMapping(value = "/ribbon-consumer",method = RequestMethod.GET)
  25. // public String helloConsumer(){
  26. // return restTemplate.getForEntity("http://SERVICE-HELLO/hello",String.class).getBody();
  27. // }
  28.  
  29. /**
  30. * @Author: StoneGeek
  31. * @Date: 2018/5/29
  32. * @Description: 加了断路器代码
  33. */
  34.  
  35. @Autowired
  36. HelloService helloService;
  37.  
  38. @RequestMapping(value = "/ribbon-consumer",method = RequestMethod.GET)
  39. public String helloConsumer(){
  40. return helloService.helloService();
  41. }
  42.  
  43. }

  此时重新来验证一下断路器实现的服务回调逻辑,此时断开8081实例,当服务消费者轮询到8081时,不再是之前的错误内容,Hystrix服务回调生效

三、模拟服务阻塞来验证断路器回调

  Hystrix默认超时时间是2000毫秒

  我们对service-hello的/hello接口做一些修改(重点是Thread.sleep()函数的使用):

  1. package com.stonegeek.controller;
  2.  
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.cloud.client.ServiceInstance;
  5. import org.springframework.cloud.client.discovery.DiscoveryClient;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RequestMethod;
  8. import org.springframework.web.bind.annotation.RestController;
  9.  
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. import java.util.Random;
  13. import java.util.logging.Logger;
  14.  
  15. /**
  16. * Created by StoneGeek on 2018/5/27.
  17. * 博客地址:http://www.cnblogs.com/sxkgeek
  18. */
  19. @RestController
  20. public class HelloController {
  21. private final Logger logger =Logger.getLogger(String.valueOf(getClass()));
  22. @Autowired
  23. private DiscoveryClient client;
  24.  
  25. /**
  26. * @Author: StoneGeek
  27. * @Date: 2018/5/29
  28. * @Description:不加线服务塞的代码
  29. */
  30. // @RequestMapping(value = "hello",method = RequestMethod.GET)
  31. // public String index(){
  32. // ServiceInstance instance=client.getLocalServiceInstance();
  33. // logger.info("/hello, host:"+instance.getHost()+", service_id:"+instance.getServiceId()+"service_port:"+instance.getPort());
  34. // return "hello world ";
  35. // }
  36.  
  37. /**
  38. * @Author: StoneGeek
  39. * @Date: 2018/5/29
  40. * @Description: 加了Thread.sleep(3000)的服务阻塞代码,由于Hystrix默认超时时间为2000毫秒,
  41. * 所以这里采用了0至3000的随机数以让处理过程有一定概率发生超时来触发断路器
  42. */
  43.  
  44. @RequestMapping(value = "/hello",method = RequestMethod.GET)
  45. public String index() throws InterruptedException {
  46. ServiceInstance instance=client.getLocalServiceInstance();
  47. int sleepTime=new Random().nextInt();
  48. logger.info("sleepTime:"+sleepTime);
  49. Thread.sleep(sleepTime);
  50. logger.info("sleepTime:"+sleepTime+"/hello, host:"+instance.getHost()+", service_id:"+instance.getServiceId()+"service_port:"+instance.getPort());
  51. return "hello world ";
  52. }
  53. }

   重新启动service-hello和ribbon-consumer模块,连续访问http://localhost:9000/ribbon-consumer几次,当RIBBON-CONSUMER的控制台输出的Spend time大于2000的时候,网页就会返回error,即服务消费者因调用的服务超时从而触发熔断请求,并调用回调逻辑返回结果

  此时Spring Could Hystrix的断路器就配置完成了!!!

  

Spring Cloud之Hystrix的更多相关文章

  1. Spring Cloud中Hystrix、Ribbon及Feign的熔断关系是什么?

    导读 今天和大家聊一聊在Spring Cloud微服务框架实践中,比较核心但是又很容易把人搞得稀里糊涂的一个问题,那就是在Spring Cloud中Hystrix.Ribbon以及Feign它们三者之 ...

  2. Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失问题分析

    最近spring boot项目中由于使用了spring cloud 的hystrix 导致了threadLocal中数据丢失,其实具体也没有使用hystrix,但是显示的把他打开了,导致了此问题. 导 ...

  3. 笔记:Spring Cloud Feign Hystrix 配置

    在 Spring Cloud Feign 中,除了引入了用户客户端负载均衡的 Spring Cloud Ribbon 之外,还引入了服务保护与容错的工具 Hystrix,默认情况下,Spring Cl ...

  4. 架构师系列文:通过Spring Cloud组件Hystrix合并请求

    在前文里,我们讲述了通过Hystrix进行容错处理的方式,这里我们将讲述通过Hystrix合并请求的方式 哪怕一个URL请求调用的功能再简单,Web应用服务都至少会开启一个线程来提供服务,换句话说,有 ...

  5. 从零开始学spring cloud(十一) -------- hystrix监控

    一.官方文档阅读 服务启动后,可以通过/health和hystrix.stream查看效果,实际上,访问上述两个地址,会出现404,这是因为spring boot版本的问题, 我在这里使用的sprin ...

  6. Spring Cloud断路器Hystrix

    在微服务架构中,存在着那么多的服务单元,若一个单元出现故障,就会因依赖关系形成故障蔓延,最终导致整个系统的瘫痪,这样的架构相较传统架构就更加的不稳定.为了解决这样的问题,因此产生了断路器模式. 什么是 ...

  7. Spring Cloud 关于 hystrix 的异常 fallback method wasn't found

    在 Spring Cloud 中使用断路器 hystrix 后,可能会遇到异常:com.netflix.hystrix.contrib.javanica.exception.FallbackDefin ...

  8. Spring Cloud之Hystrix服务保护框架

    服务保护利器 微服务高可用技术 大型复杂的分布式系统中,高可用相关的技术架构非常重要. 高可用架构非常重要的一个环节,就是如何将分布式系统中的各个服务打造成高可用的服务,从而足以应对分布式系统环境中的 ...

  9. spring cloud(五) hystrix

    开启feign 熔断 hystrix    整合hystrix-dashboard监控面板 1. 服务调用者boot工程 pom引入依赖 <!-- hystrix-dashboard 监控依赖 ...

  10. Spring Cloud 之 Hystrix.

    一.概述  在微服务架构中,我们将系统拆分成了很多服务单元,各单元的应用间通过服务注册与订阅的方式互相依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依 ...

随机推荐

  1. 2019icpc南昌网络赛_I_Yukino With Subinterval

    题意 给定一个序列,两种操作,单点修改,询问区间\([l,r]\)值域在\([x,y]\)范围内的连续段个数. 分析 原数组为\(a\),构造一个新的数组\(b\),\(b[i]=(a[i]==a[i ...

  2. [1]尝试用Unity3d制作一个王者荣耀(持续更新)->AssetBundle管理器

    如果已经看过本章节:目录传送门:这是目录鸭~ 1.AssetBundleManager: 首先我们创建一个文件夹,叫AssetBundleManager,再创建Csharp(即C#)脚本,名为Asse ...

  3. C#中Path类的常用方法

    场景 打开VS,输入Path,我们可以看到其定义. 都是静态方法,所以我们可以使用类名直接调用. 实现 新建命令行程序,编码如下: string str = @"C:\Users\Admin ...

  4. HBase shell scan 模糊查询

    0.进入hbase shell ./hbase shell help help "get" #查看单独的某个命令的帮助 1. 一般命令 status 查看状态 version 查看 ...

  5. POJ - 3984 迷宫问题 (搜索)

    Problem Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, ...

  6. setInterval、setTimeout之遗忘的第三个参数

    今天看阮一峰老师的ES6入门,在一个关于promise的小demo里,老师用到了setTimeout的第三个参数,惊了有没有,定时器还有第三个参数? 喏就是下面这个demo: function tim ...

  7. Flume系列一之架构介绍和安装

    Flume架构介绍和安装 写在前面 在学习一门新的技术之前,我们得知道了解这个东西有什么用?我们可以使用它来做些什么呢?简单来说,flume是大数据日志分析中不能缺少的一个组件,既可以使用在流处理中, ...

  8. mysql修改数据库的存储引擎(InnoDB)

    查看当前的存储引擎 show engines; 基本的差别:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不 ...

  9. js---电商中常见的放大镜效果

    js中的放大镜效果 在电商中,放大镜效果是很常见的,如下图所示: 当鼠标悬浮时,遮罩所在区域在右侧进行放大. 在动手写之前,我们要先理清思路,分析需求,所需知识点,再将每一块进行组装,最后进行功能的完 ...

  10. 使用servlet+jdbc+MD5实现用户加密登录

    /** * 分析流程: * 1.前端页面提交登录请求 * 2.被web.xml拦截,进入到LoginServlet(有两种方式:方式一,在web.xml文件中配置servlet拦截器;方式二,不用在w ...