Spring Boot中如何使用断路器详解

前言

随着使用 Spring 进行开发的个人和企业越来越多,Spring 也慢慢从一个单一简洁的小框架变成一个大而全的开源软件,Spring 的边界不断的进行扩充,到了后来 Spring 几乎可以做任何事情了,市面上主流的开源软件、中间件都有 Spring 对应组件支持,人们在享用 Spring 的这种便利之后,也遇到了一些问题。

断路器本身是电路上的一种过载保护装置,当线路中有电器发生短路时,它能够及时的切断故障电路以防止严重后果发生。通过服务熔断(也可以称为断路)、降级、限流(隔离)、异步RPC等手段控制依赖服务的延迟与失败,防止整个服务雪崩。一个断路器可以装饰并且检测了一个受保护的功能调用。根据当前的状态决定调用时被执行还是回退。通常情况下,一个断路器实现三种类型的状态:open、half-open以及closed:

  • closed状态的调用被执行,事务度量被存储,这些度量是实现一个健康策略所必备的。
  • 倘若系统健康状况变差,断路器就处在open状态。此种状态下,所有调用会被立即回退并且不会产生新的调用。open状态的目的是给服务器端回复和处理问题的时间。
  • 一旦断路器进入一个open状态,超时计时器开始计时。如果计时器超时,断路器切换到half-open状态。在half-open状态调用间歇性执行以确定问题是否已解决。如果解决,状态切换回closed状态。

断路器背后的基本思想非常简单。将受保护的函数调用包装在断路器对象中,该对象监视故障。一旦故障达到某个阈值,断路器就会跳闸,并且所有对断路器的进一步调用都会返回错误,而根本不会进行受保护的呼叫。通常,如果断路器跳闸,您还需要某种监控器警报。

如何快速使用Hystrix呢?下面跟着我1234……

1、加入@EnableCircuitBreaker注解

@EnableCircuitBreaker
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClientspublic class DroolsAppApplication {
 public static void main(String[] args) {
  SpringApplication.run(DroolsAppApplication.class, args);
 }
}

Hystrix整体执行过程,首先,Command会调用run方法,如果run方法超时或者抛出异常,且启用了降级处理,则调用getFallback方法进行降级;

2、使用@HystrixCommand注解

@HystrixCommand(fallbackMethod = "reliable")
 public String readingList() {
  for (int i = 0; i < 10; i++) {
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  return "jinpingmei";
 }

 public String reliable() {
  return "you love interesting book";
 }

3、添加引用

 compile("org.springframework.cloud:spring-cloud-starter-hystrix")
 compile('org.springframework.cloud:spring-cloud-starter-turbine')

4、设置超时时间

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

执行结果如下:

正常应该返回:

你不要喜欢jinpingmei,要喜欢有意思的书;这样使用好舒服啊,@EnableCircuitBreaker这个注解就这么强大吗?

HystrixCommandAspect 通过AOP拦截所有的@HystrixCommand注解的方法,从而使得@HystrixCommand能够集成到Spring boot中,

HystrixCommandAspect的关键代码如下:

1.方法 hystrixCommandAnnotationPointcut() 定义拦截注解HystrixCommand

2.方法 hystrixCollapserAnnotationPointcut()定义拦截注解HystrixCollapser

3.方法methodsAnnotatedWithHystrixCommand(…)通过@Around(…)拦截所有HystrixCommand和HystrixCollapser注解的方法。详细见方法注解

@Aspect
public class HystrixCommandAspect {

 private static final Map<HystrixPointcutType, MetaHolderFactory> META_HOLDER_FACTORY_MAP;

 static {
  META_HOLDER_FACTORY_MAP = ImmutableMap.<HystrixPointcutType, MetaHolderFactory>builder()
    .put(HystrixPointcutType.COMMAND, new CommandMetaHolderFactory())
    .put(HystrixPointcutType.COLLAPSER, new CollapserMetaHolderFactory())
    .build();
 }

 @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")

 public void hystrixCommandAnnotationPointcut() {
 }

 @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
 public void hystrixCollapserAnnotationPointcut() {
 }

 @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
 public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
  Method method = getMethodFromTarget(joinPoint);
  Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
  if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
   throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
     "annotations at the same time");
  }
  MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
  MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
  HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
  ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
    metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
  Object result;
  try {
   result = CommandExecutor.execute(invokable, executionType, metaHolder);
  } catch (HystrixBadRequestException e) {
   throw e.getCause();
  }
  return result;
 }

那么HystrixCommandAspect是如何初始化,是通过HystrixCircuitBreakerConfiguration实现的

@Configuration
public class HystrixCircuitBreakerConfiguration {

@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
}

那么谁来触发HystrixCircuitBreakerConfiguration执行初始化

先看spring-cloud-netflix-core**.jar包的spring.factories里有这段配置,是由注解EnableCircuitBreaker触发

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration

那么@EnableCircuitBreaker如何触发HystrixCircuitBreakerConfiguration

通过源码查看,此类通过@Import初始化EnableCircuitBreakerImportSelector类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableCircuitBreakerImportSelector.class)
public @interface EnableCircuitBreaker {
}

EnableCircuitBreakerImportSelector是SpringFactoryImportSelector子类。此类在初始化后,会执行selectImports(AnnotationMetadata metadata)的方法。此方法会根据注解启动的注解(这里指@EnableCircuitBreaker)从spring.factories文件中获取其配置需要初始化@Configuration类(这里是org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration),从而最终初始化HystrixCommandAspect 类,从而实现拦截HystrixCommand的功能

以上就是通过@EnableCircuitBreake可以开启Hystrix的原理。Hystrix用到了观察者模式AbstractCommand.executeCommandAndObserve()模式,下次我们来深入说一下观察者模式。欢迎拍砖!

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 详解SpringCloud微服务架构之Hystrix断路器

    一:什么是Hystrix 在分布式环境中,许多服务依赖项中的一些将不可避免地失败.Hystrix是一个库,通过添加延迟容差和容错逻辑来帮助您控制这些分布式服务之间的交互.Hystrix通过隔离服务之间的访问点,停止其间的级联故障以及提供回退选项,从而提高系统的整体弹性. Hystrix旨在执行以下操作 1:对通过第三方客户端库访问(通常通过网络)的依赖关系提供保护并控制延迟和故障. 2:隔离复杂分布式系统中的级联故障. 3:快速发现故障,尽快恢复. 4:回退,尽可能优雅地降级. 5:启用近实时监

  • 详解Spring Cloud 断路器集群监控(Turbine)

    一. 简介 上一篇文章我们已经实现了对单个服务实例的监控,当然在实际应用中,单个实例的监控数据没有多大的价值,我们更需要的是一个集群系统的监控信息,这时我们就需要引入Turbine.Turbine能够汇集监控信息,并将聚合后的信息提供给Hystrix Dashboard来集中展示和监控. 二. 构建监控局和服务 2.1 整体结构与准备 本文的工程实现是基于上一篇文章的工程,通过引入Turbine来聚合service-ribbon服务的监控信息,并输出给Hystrix Dashboard来进行展示

  • 详解Spring Cloud 熔断机制--断路器

    断路器(Curcuit Breaker)模式 在分布式环境下,特别是微服务结构的分布式系统中, 一个软件系统调用另外一个远程系统是非常普遍的.这种远程调用的被调用方可能是另外一个进程,或者是跨网路的另外一台主机, 这种远程的调用和进程的内部调用最大的区别是,远程调用可能会失败,或者挂起而没有任何回应,直到超时.更坏的情况是, 如果有多个调用者对同一个挂起的服务进行调用,那么就很有可能的是一个服务的超时等待迅速蔓延到整个分布式系统,引起连锁反应, 从而消耗掉整个分布式系统大量资源.最终可能导致系统

  • spring cloud 使用Hystrix 实现断路器进行服务容错保护的方法

    在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖.但是如果有一些服务出现问题了会怎么样? 比如说有三个服务(ABC),A调用B,B调用C.由于网络延迟或C本身代码有问题导致B迟迟得不到回应,这样B调用C的请求就会被挂起,等待. 在高并发的访问的情况下,这些挂起的线程得不到释放,使后续的请求阻塞,最终导致B也挂掉了.依次类推,A可能也会挂掉,进而使整个系统全部崩溃. 为了解决整个问题,Spring Cloud 使用Hystrix进行服务容错保护,包括断

  • 详解Spring Cloud Hystrix断路器实现容错和降级

    简介 Spring cloud提供了Hystrix容错库用以在服务不可用时,对配置了断路器的方法实行降级策略,临时调用备用方法.这篇文章将创建一个产品微服务,注册到eureka服务注册中心,然后我们使用web客户端访问/products API来获取产品列表,当产品服务故障时,则调用本地备用方法,以降级但正常提供服务. 基础环境 JDK 1.8 Maven 3.3.9 IntelliJ 2018.1 Git:项目源码 添加产品服务 在intelliJ中创建一个新的maven项目,使用如下配置 g

  • spring cloud Hystrix断路器的使用(熔断器)

    1.Hystrix客户端 Netflix已经创建了一个名为Hystrix的库,实现了断路器的模式.在microservice架构通常有多个层的服务调用. 低水平的服务的服务失败会导致级联故障一直给到用户.当调用一个特定的服务达到一定阈值(默认5秒失败20次),打开断路器.在错误的情况下和一个开启的断路回滚应可以由开发人员提供. 有一个断路器阻止级联失败并且允许关闭服务一段时间进行愈合.回滚会被其他hystrix保护调用,静态数据或健全的空值. 代码如下: @SpringBootApplicati

  • Spring Boot中如何使用断路器详解

    前言 随着使用 Spring 进行开发的个人和企业越来越多,Spring 也慢慢从一个单一简洁的小框架变成一个大而全的开源软件,Spring 的边界不断的进行扩充,到了后来 Spring 几乎可以做任何事情了,市面上主流的开源软件.中间件都有 Spring 对应组件支持,人们在享用 Spring 的这种便利之后,也遇到了一些问题. 断路器本身是电路上的一种过载保护装置,当线路中有电器发生短路时,它能够及时的切断故障电路以防止严重后果发生.通过服务熔断(也可以称为断路).降级.限流(隔离).异步R

  • Spring Boot中如何使用Swagger详解

    目录 Swagger 简介 配置 Swagger 添加依赖 为项目开启 Swagger 创建 SwaggerConfig 配置类 访问 Swagger 前端页面 控制器相关注解 实体相关注解 总结 Swagger 简介 Swagger 是一个方便 API 开发的框架,它有以下优点: 自动生成在线文档,后端开发人员的改动可以立即反映到在线文档,并且不用单独编写接口文档,减轻了开发负担 支持通过 Swagger 页面直接调试接口,方便前端开发人员进行测试 配置 Swagger Swagger 目前有

  • spring boot的maven配置依赖详解

    本文介绍了spring boot的maven配置依赖详解,分享给大家,具体如下: 我们通过引用spring-boot-starter-parent,添加spring-boot-starter-web 可以实现web项目的功能,当然不使用spring-boot-start-web,通过自己添加的依赖包也可以实现,但是需要一个个添加,费时费力,而且可能产生版本依赖冲突.我们来看下springboot的依赖配置: 利用pom的继承,一处声明,处处使用.在最顶级的spring-boot-dependen

  • spring Boot与Mybatis整合优化详解

    SpringBoot官方文档http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ 关于spring-boot与mybatis整合优化方面的介绍,就是Mybatis-Spring-boot-starter的介绍: 1.取消spring-mybatis.xml配置 ①自动检测已存在的Datasource 之前,需要在spring-mybatis.xml中配置datasource的Bean,现在只需要在applicat

  • spring boot(四)之thymeleaf使用详解

    在上篇文章springboot(二):web综合开发中简单介绍了一下thymeleaf,这篇文章将更加全面详细的介绍thymeleaf的使用.thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎. thymeleaf介绍 简单说, Thymeleaf 是一个跟 Velocity.FreeMarker 类似的模板引擎,它可以完全替代 JSP .相较与其他的模板引擎,它有如下三个极吸引人的特点: 1.Thymeleaf 在有网络和无网络的环境下皆可

  • Spring boot跨域设置实例详解

    定义:跨域是指从一个域名的网页去请求另一个域名的资源 1.原由 公司内部有多个不同的子域,比如一个是location.company.com ,而应用是放在app.company.com , 这时想从 app.company.com去访问 location.company.com 的资源就属于跨域 本人是springboot菜鸟,但是做测试框架后端需要使用Springboot和前端对接,出现跨域问题,需要设置后端Response的Header.走了不少坑,在这总结一下以备以后使用 2.使用场景

  • Spring boot的上传图片功能实例详解

    简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. 特点 1. 创建独立的Spring应用程序 2. 嵌入的Tomcat,无需部署WAR文件 3. 简化Maven配置 4. 自动配置Spring 5. 提

  • Spring Boot整合EhCache的步骤详解

    本文讲解Spring Boot与EhCache的整合. 1 EhCache简介 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认CacheProvider.Ehcache是一种广泛使用的开源Java分布式缓存.主要面向通用缓存,Java EE和轻量级容器.它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点. 2 Spring Boot整合EhCache步骤 2.

  • Spring Boot示例代码整合Redis详解

    目录 Redis 简介 Redis 优势 Redis与其他key-value存储有什么不同 添加Redis依赖包 配置Redis数据库连接 编写Redis操作工具类 测试 Redis 简介 Redis 是完全开源的,遵守 BSD 协议,是一个高性能的 key-value 数据库. Redis 与其他 key - value 缓存产品有以下三个特点: Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用. Redis不仅仅支持简单的key-value类型的数据

  • Spring boot Thymeleaf配置国际化页面详解

    目录 1.编写多语言国际化配置文件 2.编写配置文件 3.定制区域信息解析器 4.页面国际化使用 5.整合效果测试 1.编写多语言国际化配置文件 在项目的类路径resources下创建名称为i18n的文件夹,并在该文件夹中根据需要编写对应的多语言国际化文件login.properties.login_zh_CN.properties和login_en_US.properties文件 login.properties login.tip=请登录login.username=用户名login.pas

随机推荐