在分布式系统中服务与服务之间的依赖错综复杂,一种不可避免的情况就是某些服务会出现故障,导致依赖于他们的其他服务出现远程调度的线程阻塞。某个服务的单个点的请求故障会导致用户的请求处于阻塞状态,最终的结果是整个服务的线程资源消耗殆尽。由于服务的依赖性,会导致依赖于该故障服务的其他服务也处于线程阻塞状态,最终导致这些服务的线程资源消耗殆尽,知道不可用,从而导致整个服务系统不可用,即雪崩效应。为了防止雪崩效应,产生了熔断器模型。

Hystrix是Netflix公司开源的一个项目,提供了熔断器功能,能阻止分布式系统中出现联动故障。Hystrix是通过隔离服务的访问点阻止联动故障的,并提供了故障解决方案,从而提高了整个分布式系统的弹性。

当服务的某个API接口的失败次数在一定时间内小于设定的阈值时,熔断器处于关闭状态,该API接口正常提供服务。当该API接口处理请求的失败次数大于设定的阈值时,hystrix判定该API接口出现了故障,打开熔断器,这时请求该API接口会执行快速失败的逻辑(即fallback回退的逻辑),不执行业务逻辑,请求的线程不会处于阻塞状态。处于打开状态的熔断器,一段时间后会处于半打开状态,并将一定数量的请求执行正常逻辑,剩余的请求会执行快速失败,若执行正常逻辑的请求失败了,则熔断器继续打开,若成功了,则关闭熔断器。这样熔断器就具有了自我修复的能力。

在RestTemplate和Ribbon上使用熔断器

需要已经成功配置Ribbon,可参考:spring boot 2.0.3+spring cloud (Finchley)2、搭建负载均衡Ribbon (Eureka+Ribbon+RestTemplate)

在eureka-ribbon-client工程中,使用了RestTemplate调用了eureka-client的“/hi”API接口,并使用ribbon做了负载均衡,在此基础上加入Hystrix熔断器功能。在pom文件中加入Hystrix起步依赖spring-cloud-starter-netflix-hystrix

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5.  
  6. <groupId>com.cralor</groupId>
  7. <artifactId>eureka-ribbon-client</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. <packaging>jar</packaging>
  10.  
  11. <name>eureka-ribbon-client</name>
  12. <description>Demo project for Spring Boot</description>
  13.  
  14. <parent>
  15. <groupId>com.cralor</groupId>
  16. <artifactId>chap8-hystrix</artifactId>
  17. <version>0.0.1-SNAPSHOT</version>
  18. <relativePath/> <!-- lookup parent from repository -->
  19. </parent>
  20.  
  21. <properties>
  22. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  23. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  24. <java.version>1.8</java.version>
  25. </properties>
  26.  
  27. <dependencies>
  28. <dependency>
  29. <groupId>org.springframework.cloud</groupId>
  30. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework.cloud</groupId>
  34. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  35. </dependency>
  36. <dependency>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-starter-test</artifactId>
  39. <scope>test</scope>
  40. </dependency>
  41. </dependencies>
  42.  
  43. <build>
  44. <plugins>
  45. <plugin>
  46. <groupId>org.springframework.boot</groupId>
  47. <artifactId>spring-boot-maven-plugin</artifactId>
  48. </plugin>
  49. </plugins>
  50. </build>
  51.  
  52. </project>

在项目启动类加上@EnableHystrix注解,开启hystrix熔断器功能

  1. @EnableHystrix
  2. @SpringBootApplication
  3. public class EurekaRibbonClientApplication {
  4.  
  5. public static void main(String[] args) {
  6. SpringApplication.run(EurekaRibbonClientApplication.class, args);
  7. }
  8. }

修改RibbonService代码,在hi()方法上加上@HystrixCommand注解。有了该注解hi()方法就启用了Hystrix熔断器的功能,其中,fallbackMethod为处理回退(fallback)逻辑的方法。在本例子,直接返回了一个字符串。在熔断器打开的状态下,会执行fallback逻辑。fallback的逻辑最好是返回一些静态的字符串,不需要处理复杂的逻辑,也不会远程调用其他服务,这样方便执行快速失败,释放线程资源。如果一定要在fallback逻辑中远程调用其他服务,最好在远程调用其他服务时,也加上熔断器。

  1. @Service
  2. public class RibbonService {
  3. @Autowired
  4. RestTemplate restTemplate;
  5.  
  6. @HystrixCommand(fallbackMethod = "hiError")
  7. public String hi(String name){
  8. return restTemplate.getForObject("http://eureka-client/hi?name="+name,String.class);
  9. }
  10. public String hiError(String name){
  11. return "hi,"+name+",sorry,error!";
  12. }
  13. }

RibbonConfig类

  1. @Configuration
  2. public class RibbonConfig {
  3. @Bean
  4. @LoadBalanced
  5. RestTemplate restTemplate(){
  6. return new RestTemplate();
  7. }
  8. }

RibbonController类

  1. @RestController
  2. public class RibbonController {
  3. @Autowired
  4. private RibbonService ribbonService;
  5.  
  6. @GetMapping("/hi")
  7. public String hi(@RequestParam(required = false,defaultValue = "cralor") String name){
  8. return ribbonService.hi(name);
  9. }
  10. }

依次启动eureka-server、eureka-client和eureka-ribbon-client。在浏览器访问http://localhost:8764/hi,会显示

关闭eureka-client,使其处于不可以状态,此时eureka-ribbon-client无法调用eureka-client的“/hi”接口,访问http://localhost:8764/hi

由此可见,当eureka-client不可用时,调用eureka-ribbon-client的”/hi“接口会进入RibbonSerivce类的”/hi“方法。由于eureka-client没有响应,判定不可用,开启了熔断器,最后进入了fallbackMethod的逻辑。之后的请求会直接执行fallbackMethod的逻辑。

在Feign上使用熔断器

Feign的起步依赖中已经引入了Hystrix的依赖,只需要在eureka-feign-client工程的配置文件中开启hystrix功能即可,

  1. server:
  2. port: 8765
  3. spring:
  4. application:
  5. name: eureka-feign-client
  6. eureka:
  7. client:
  8. serviceUrl:
  9. defaultZone: http://localhost:8761/eureka/
  10. feign:
  11. hystrix:
  12. enabled: true

修改EurekaClientFeign代码,在@FeignClient注解的fallback配置加上快速失败的处理类。该处理类是作为geign熔断器的逻辑处理类,必须实现被@FeignClient修饰的接口。

EurekaClientFeign类

  1. @Component
  2. @FeignClient(value = "eureka-client",configuration = FeignConfig.class,fallback = HiHystrix.class)
  3. public interface EurekaClientFeign {
  4. @GetMapping(value = "/hi")
  5. String sayHiFromClientEureka(@RequestParam(value = "name")String name);
  6. }

HiHystrix 类

  1. @Component
  2. public class HiHystrix implements EurekaClientFeign {
  3.  
  4. @Override
  5. public String sayHiFromClientEureka(String name) {
  6. return "hi,"+name+",sorry.error!";
  7. }
  8. }

FeignConfig类

  1. @Configuration
  2. public class FeignConfig {
  3. @Bean
  4. public Retryer feignRetryer(){
  5. return new Retryer.Default(100,TimeUnit.SECONDS.toMillis(1),5);
  6. }
  7. }

HiService 类

  1. @Service
  2. public class HiService {
  3. @Autowired
  4. EurekaClientFeign eurekaClientFeign;
  5.  
  6. public String sayHi(String name){
  7. return eurekaClientFeign.sayHiFromClientEureka(name);
  8. }
  9. }

HiController 类

  1. @RestController
  2. public class HiController {
  3. @Autowired
  4. HiService hiService;
  5.  
  6. @GetMapping("/hi")
  7. public String sayHi(@RequestParam(defaultValue = "cralor",required = false)String name){
  8. return hiService.sayHi(name);
  9. }
  10. }

启动工程eureka-server、eureka-client和eureka-feign-client,浏览器访问http://localhost:8765/hi

关闭eureka-client

由此可见,当eureka-client不可以时,eureka-feign-client进入了fallback的逻辑处理类HiHystrix,由这个类来执行熔断器打开时的处理逻辑。

使用Hystrix Dashboard监控熔断器的状态

Hystrix Dashboard时监控Hystrix的熔断器的一个组件,提供了数据监控和友好的展示界面。

在Rest Template中使用Hystrix Dashboard

在eureka-ribbon-client工程的pom文件加上Actuator、Hystrix 和Hystrix Dashboard的起步依赖,这三个依赖是必需的。

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4. </dependency>
  5.  
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  9. </dependency>
  10.  
  11. <dependency>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-actuator</artifactId>
  14. </dependency>
  15.  
  16. <dependency>
  17. <groupId>org.springframework.cloud</groupId>
  18. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  19. </dependency>

修改配置文件,启动actuator监控

  1. server:
    port: 8764
    spring:
    application:
    name: eureka-ribbon-client
    eureka:
    client:
    serviceUrl:
    defaultZone: http://localhost:8761/eureka/
  2.  
  3. #springboot2.0. 的配置项为:
    #actuator端口
    management:
    server:
    port: 9001
    endpoints:
    web:
    # base-path: / #修改访问路径 2.0之前默认是/ 2.0默认是 /actuator 可以通过这个属性值修改
    exposure:
    include: '*' #开放所有页面节点 默认只开启了health、info两个节点

在程序启动类加上@EnableHystrixDashboard注解,

  1. @EnableHystrixDashboard
  2. @EnableHystrix
  3. @SpringBootApplication
  4. public class EurekaRibbonClientApplication {
  5.  
  6. public static void main(String[] args) {
  7. SpringApplication.run(EurekaRibbonClientApplication.class, args);
  8. }
  9. }

依次启动eureka-server、eureka-client和eureka-ribbon-client。在浏览器访问先访问http://localhost:8764/hi,然后再访问http://localhost:9001/actuator/hystrix.stream,浏览器会显示熔断器的数据指标

在浏览器访问http://localhost:8764/hystrix,注意:端口号为具体服务对应的端口号而不是Eureka Server的端口号

依次填写http://localhost:9001/actuator/hystrix.stream、2000、cralor(随意填写),点击 moniter

该页面显示了熔断器的谷中数据指标,这些数据指标含义如图,该图来自于Hystrix官方文档,文档地址:https://github.com/Netflix/Hystrix/wiki

在Feign中使用Hystrix Dashboard

在eureka-feign-client的pom文件加上Actuator、Hystrix和Dashboard的起步依赖,(Feign自带的Hystrix依赖不是起步依赖,还需要加上起步依赖)

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4. </dependency>
  5.  
  6. <dependency>
  7. <groupId>org.springframework.cloud</groupId>
  8. <artifactId>spring-cloud-starter-openfeign</artifactId>
  9. </dependency>
  10.  
  11. <dependency>
  12. <groupId>org.springframework.cloud</groupId>
  13. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  14. </dependency>
  15.  
  16. <dependency>
  17. <groupId>org.springframework.cloud</groupId>
  18. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  19. </dependency>
  20.  
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-actuator</artifactId>
  24. </dependency>

启动类加上注解@EnableHystrixDashboard,@EnableHystrix

  1. @EnableHystrixDashboard
  2. @EnableHystrix
  3. @EnableFeignClients
  4. @SpringBootApplication
  5. public class EurekaFeignClientApplication {
  6.  
  7. public static void main(String[] args) {
  8. SpringApplication.run(EurekaFeignClientApplication.class, args);
  9. }
  10. }

启动即可,其他步骤跟ribbon一样。

使用Turbine聚合监控

在使用Hystrix Dashboard组件监控服务的熔断器状况时,每个服务都有一个Hystrix Dashboard主页,服务数量过多时,监控非常不方便。Netflix开源了另一个组件Turbine,用于聚合多个Hystrix Dashboard,将数据显示在一个页面上,集中监控。

新建一个module工程eureka-monitor-client,作为Turbine聚合监控的工程。pom文件引入相关actuator、hystrix dashboard和turbine的起步依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5.  
  6. <groupId>com.cralor</groupId>
  7. <artifactId>eureka-monitor-client</artifactId>
  8. <version>0.0.1-SNAPSHOT</version>
  9. <packaging>jar</packaging>
  10.  
  11. <name>eureka-monitor-client</name>
  12. <description>Demo project for Spring Boot</description>
  13.  
  14. <parent>
  15. <groupId>com.cralor</groupId>
  16. <artifactId>chap8-hystrix</artifactId>
  17. <version>0.0.1-SNAPSHOT</version>
  18. <relativePath/> <!-- lookup parent from repository -->
  19. </parent>
  20.  
  21. <properties>
  22. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  23. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  24. <java.version>1.8</java.version>
  25. </properties>
  26.  
  27. <dependencies>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-actuator</artifactId>
  31. </dependency>
  32.  
  33. <dependency>
  34. <groupId>org.springframework.cloud</groupId>
  35. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  36. </dependency>
  37.  
  38. <dependency>
  39. <groupId>org.springframework.cloud</groupId>
  40. <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
  41. </dependency>
  42.  
  43. <dependency>
  44. <groupId>org.springframework.boot</groupId>
  45. <artifactId>spring-boot-starter-test</artifactId>
  46. <scope>test</scope>
  47. </dependency>
  48. </dependencies>
  49.  
  50. <build>
  51. <plugins>
  52. <plugin>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-maven-plugin</artifactId>
  55. </plugin>
  56. </plugins>
  57. </build>
  58.  
  59. </project>

修改配置文件

  1. server:
  2. port: 8769
  3. spring:
  4. application:
  5. name: service-turbine
  6. eureka:
  7. client:
  8. serviceUrl:
  9. defaultZone: http://localhost:8761/eureka/
  10.  
  11. #springboot2.0. 的配置项为:
  12. #actuator端口
  13. management:
  14. # server:
  15. # port: 9007
  16. endpoints:
  17. web:
  18. # base-path: /monitor #修改访问路径 2.0之前默认是/ 2.0默认是 /actuator 可以通过这个属性值修改
  19. exposure:
  20. include: '*' #开放所有页面节点 默认只开启了health、info两个节点
  21.  
  22. turbine:
  23. aggregator:
  24. cluster-config: default #需要监控的服务集群名
  25. app-config: eureka-ribbon-client,eureka-feign-client #需要监控的服务名
  26. cluster-name-expression: new String("default")
  27. # instanceUrlSuffix:
  28. # default: actuator/hystrix.stream #key是clusterConfig集群的名字,value是hystrix监控的后缀,springboot2.0为actuator/hystrix.stream

在启动类加上注解

  1. @EnableTurbine
  2. @EnableHystrixDashboard
  3. @SpringBootApplication
  4. public class EurekaMonitorClientApplication {
  5.  
  6. public static void main(String[] args) {
  7. SpringApplication.run(EurekaMonitorClientApplication.class, args);
  8. }
  9. }

启动工程eureka-server、eureka-client、eureka-ribbon-client、eureka-feign-client和eureka-monitor-client,在浏览器访问http://localhost:8764/hi,http://localhost:8765/hi,在浏览器打开http://localhost:8764/hystrix(端口号8764、8765、8769都可以),依次填入http://localhost:8769/turbine.stream,2000,cralor,点击”monitor“,

可以看到这个页面聚合了eureka-ribbon-client和eureka-feign-client的Hystrix Dashboard数据。

参考:https://windmt.com/2018/04/15/spring-cloud-4-hystrix/

https://windmt.com/2018/04/16/spring-cloud-5-hystrix-dashboard/

https://windmt.com/2018/04/17/spring-cloud-6-turbine/

案例代码地址:https://github.com/cralor7/springcloud

 

spring boot 2.0.3+spring cloud (Finchley)4、熔断器Hystrix的更多相关文章

  1. spring boot 2.0.3+spring cloud (Finchley)3、声明式调用Feign

    Feign受Retrofix.JAXRS-2.0和WebSocket影响,采用了声明式API接口的风格,将Java Http客户端绑定到他的内部.Feign的首要目标是将Java Http客户端调用过 ...

  2. spring boot 2.0.3+spring cloud (Finchley)2、搭建负载均衡Ribbon (Eureka+Ribbon+RestTemplate)

    Ribbon是Netflix公司开源的一个负载均衡组件,将负载均衡逻辑封装在客户端中,运行在客户端的进程里. 本例子是在搭建好eureka的基础上进行的,可参考spring boot 2.0.3+sp ...

  3. spring boot 2.0.3+spring cloud (Finchley)5、路由网关Spring Cloud Zuul

    Zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态路由.过滤.监控.弹性伸缩和安全. 为什么需要Zuul Zuul.Ribbon以及Eureka结合可以实现智能路由和负载均衡的功能:网关将 ...

  4. spring boot 2.0.3+spring cloud (Finchley)7、服务链路追踪Spring Cloud Sleuth

    参考:Spring Cloud(十二):分布式链路跟踪 Sleuth 与 Zipkin[Finchley 版] Spring Cloud Sleuth 是Spring Cloud的一个组件,主要功能是 ...

  5. spring boot 2.0.3+spring cloud (Finchley)8、微服务监控Spring Boot Admin

    参考:Spring Boot Admin 2.0 上手 Spring Boot Admin 用于管理和监控一个或多个Spring Boot程序,在 Spring Boot Actuator 的基础上提 ...

  6. spring boot 2.0.3+spring cloud (Finchley)1、搭建服务注册和发现组件Eureka 以及构建高可用Eureka Server集群

    一 .搭建Eureka 编写Eureka Server 由于有多个spring boot项目,采用maven多module的结构,项目结构如下: 新建一个maven主工程,在主maven的pom文件中 ...

  7. spring boot 2.0.3+spring cloud (Finchley)6、配置中心Spring Cloud Config

    https://www.cnblogs.com/cralor/p/9239976.html Spring Cloud Config 是用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持, ...

  8. spring boot 2.0.3+spring cloud (Finchley)9、 安全组件Spring Boot Security

    官方文档 一.Spring Security介绍 Spring Security是Spring Resource社区的一个安全组件,Spring Security为JavaEE企业级开发提供了全面的安 ...

  9. Spring Boot 2.0 利用 Spring Security 实现简单的OAuth2.0认证方式1

    0. 前言 之前帐号认证用过自己写的进行匹配,现在要学会使用标准了.准备了解和使用这个OAuth2.0协议. 1. 配置 1.1 配置pom.xml 有些可能会用不到,我把我项目中用到的所有包都贴出来 ...

随机推荐

  1. VMware提示无法打开内核设备 \\.\Global\vmx86: 系统找不到指定的文件解决方案

    1.右键单击[我的电脑],选择[管理] 2.在[服务]中找到VMware Workstation Server服务右键启动

  2. springmvc 路由

    工作中MVC是较常使用的web框架,作为研发人员,也习惯了以编写Controller作为项目开始,写好了Controller和对应的方法,加上@RequestMapping注解,我们也就认为一切已经准 ...

  3. GO语言教程(一)Linux( Centos)下Go的安装, 以及HelloWorld

    写在前面: 目前,Go语言已经发布了1.5的版本,已经有不少Go语言相关的书籍和教程了,但是看了一些后,觉得还是应该自己写一套Go语言的教程.给广大学习Go语言的朋友多一种选择.因为,咱写的教程,向来 ...

  4. Git命令常用清单

    本文从以下十个方面,介绍Git命令的常用清单: 一.新建代码库 二.配置 三.增加/删除文件 四.代码提交 五.分支 六.标签 七.查看信息 八.远程同步 九.撤销 十.其他 每天使用 Git ,但是 ...

  5. python接口自动化测试框架实现之字符串插入变量(字符串参数化)

    问题: 在做接口自动化测试的时候,请求报文是json串,但是根据项目规则必须转换成字符串,然后在开头拼接“data=” 接口中很多入参值需要进行参数化. 解决方案: 1.Python并没有对在字符串中 ...

  6. influxdb 命令

    写入数据: curl -X POST -d '[{"name":"foo","columns":["val"],&quo ...

  7. mysql流程控制语句

    mysql编程 mysql编程中语句块包含符: 其实就是相当于js或php中大括号语法: [标识符:]begin //语句.... end  [标识符]: 标识符就是定义定义的任意的名字而已,比如: ...

  8. 解决Lenovo(ldeapad)笔记本F1-F12功能键操作无效的问题

    1.操作条件:Lenovo笔记本自带的“一键恢复”按钮 2.操作方法:上下键为切换选项,回车键(Enter)为确定选择 (1)在笔记本电脑关机状态下,使用曲别针或其他物件按下笔记本自带的“一键恢复按钮 ...

  9. CODE FESTIVAL 2016 qualA Grid and Integers

    划年代久远的水 题意 有一个R*C的棋盘,要求在每个格子上填一个非负数,使得对任意一个2*2的正方形区域,左上角和右下角的数字之和等于左下角和右上角的数字之和.有一些格子已经被填上了数字,问现在能否满 ...

  10. 【uoj#174】新年的破栈 贪心

    题目描述 给你一个长度为 $n$ 的序列和一个空的双端队列,每次进行3种操作种的一种: 1.将序列中编号最小的数加入到双端队列的队尾:2.从双端队列的队尾取出一个数:3.从双端队列的队头取出一个数. ...