通过@HystrixCommand注解实现在Spring Cloud使用Hystrix组件相关的工程

  • cloud-registration-center:注册中心
  • cloud-service-hystrix: 作为服务方的工程
  • cloud-consumer-hystrix:通过hystrix调用cloud-service-hystrix的接口

1.cloud-service-hystrix

作为服务方的工程,此工程比较简单,

bootstrap-hystrix.yml

只列出部分内容

spring:
application:
# 本服务注册到注册到服务器的名称, 这个名称就是后面调用服务时的服务标识符
name: cloud-hystrix-service
….
 

2.SimpleCtl:提供服务的Control类

@RestController
public class SimpleCtl {
private AtomicInteger count = new AtomicInteger();
private AtomicInteger sleepCount = new AtomicInteger(); @RequestMapping(value="/hystrix/simp le")
public String hystrixClientCall(@RequestParam("time") long time){
int newCount = count.incrementAndGet();
return "time " + time + " hystrix" + newCount + ": " + ThreadLocalRandom.current().nextInt(1000);
}
……
}

3.cloud-consumer-hystrix

通过hystrix调用cloud-service-hystrix的接口

pom.xml:只列出关键的jar

 <!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

  bootstrap-hystrix-simple.yml属性配置

# port
server:
port: 12083 spring:
application:
# 本服务注册到注册到服务器的名称, 这个名称就是后面调用服务时的服务标识符
name: cloud-consumer-hystrix
eureka:
client:
serviceUrl:
# 服务器注册/获取服务器的zone
defaultZone: http://127.0.0.1:10761/eureka/
instance:
prefer-ip-address: true

4.MyHystrixClient

功能:通过RestTemplate调用服务的接口

  • @HystrixCommand:此注解表示此方法是hystrix方法,其中fallbackMethod定义回退方法的名称
  • String myFallback(long p, Throwable e) :HystrixCommand的回退方法,此方法必须和hystrix的执行方法在相同类中。可以把HystrixCommand的执行参数和执行失败的异常传入回退方法中
@Service
public class MyHystrixClient {
@Autowired
private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "myFallback")
public String simpleHystrixClientCall(long time) {
return restTemplate.getForEntity("http://CLOUD-HYSTRIX-SERVICE/hystrix/simple?time=" + time, String.class).getBody();
} /**
* 方法simpleHystrixClientCall的回退方法,可以指定将hystrix执行失败异常传入到方法中
* @param p ystrix执行失败的传入方法的请求
* @param e hystrix执行失败的异常对象
* @return
*/
String myFallback(long p, Throwable e) {
return "Execute raw fallback: access service fail , req= " + p + " reason = " + e;
}

@HystrixCommand:其他参数说明
 public @interface HystrixCommand {

            // HystrixCommand 命令所属的组的名称:默认注解方法类的名称
String groupKey() default ""; // HystrixCommand 命令的key值,默认值为注解方法的名称
String commandKey() default ""; // 线程池名称,默认定义为groupKey
String threadPoolKey() default "";
// 定义回退方法的名称, 此方法必须和hystrix的执行方法在相同类中
String fallbackMethod() default "";
// 配置hystrix命令的参数
HystrixProperty[] commandProperties() default {};
// 配置hystrix依赖的线程池的参数
HystrixProperty[] threadPoolProperties() default {}; // 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。我们也可以通过此方法定义哪些需要忽略的异常
Class<? extends Throwable>[] ignoreExceptions() default {}; // 定义执行hystrix observable的命令的模式,类型详细见ObservableExecutionMode
ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER; // 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。此方法定义需要抛出的异常
HystrixException[] raiseHystrixExceptions() default {}; // 定义回调方法:但是defaultFallback不能传入参数,返回参数和hystrix的命令兼容
String defaultFallback() default "";
}

SimpleCtl

通过Control的方法调用MyHystrixClient的方法,返回执行结果

@RestController
public class SimpleCtl {
@Autowired
private MyHystrixClient myHystrixClient; @RequestMapping(value="/hystrix/simple")
public String simpleClientCall(){
return "rsp: " + myHystrixClient.simpleHystrixClientCall(System.currentTimeMillis());
} }
 

配置Hystrix的自定义参数


以下时配置hystrix的线程池的大小,其他的配置见Spring cloud系列九 Hystrix的配置属性优先级和详解


application-hystrix-simple.yml


# 配置hystrix的参数
hystrix:
threadpool:
# default: 默认参数,作用的所有的hystrix的客户端
default:
coreSize: 10

启动类HystrixSimpleCloudConsumerApplication

  • @EnableCircuitBreaker :启动断路器
  • 方法RestTemplate restTemplate():初始化RestTemplate 对象,并使用 @LoadBalanced作负载均衡
@SpringBootApplication
@EnableCircuitBreaker
@EnableEurekaClient // 配置本应用将使用服务注册和服务发现
public class HystrixSimpleCloudConsumerApplication { public static void main(String[] args) {
args = new String[1];
args[0] = "--spring.profiles.active=hystrix-simple";
SpringApplication.run(HystrixSimpleCloudConsumerApplication.class, args);
} /**
* 初始RestTemplate
* @return
*/
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
} /**
* 使用fastjson做为json的解析器
* @return
*/
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
}

6.测试

启动服务

启动工程cloud-registration-center:配置中心地址:http://127.0.0.1:10761 
启动工程cloud-service-hystrix的HystrixCloudServiceApplication的启动类 
启动工程cloud-consumer-hystrix的HystrixSimpleCloudConsumerApplication的启动类

测试一 
执行cloud-consumer-hystrix的调用cloud-service-hystrix服务的接口 
在浏览器中运行URL: http://127.0.0.1:12083//hystrix/simple 
返回:

"rsp: \"time 1511015252093 hystrix1: 434\""

测试二 
停止cloud-service-hystrix服务 
执行cloud-consumer-hystrix的调用cloud-service-hystrix服务的接口 
在浏览器中运行URL: http://127.0.0.1:12083//hystrix/simple 
返回:

"rsp: Execute raw fallback: access service fail , req= 1511103681411 reason = com.netflix.hystrix.exception.HystrixTimeoutException"

说明fallback方法被执行了

测试三 
修改application-hystrix-simple.yml 中的hystrix的线程池的线程数量为0,

# 配置hystrix的参数
hystrix:
threadpool:
# default: 默认参数,作用的所有的hystrix的客户端
default:
coreSize: 0

重启cloud-service-hystrix和cloud-consumer-hystrix, 
执行http://127.0.0.1:12083//hystrix/simple 
提示执行hystrix方法失败,说明我们的配置启作用了

@EnableCircuitBreaker的原理

在启动类HystrixSimpleCloudConsumerApplication中使用@EnableCircuitBreaker + @HystrixCommand 注解启动Hystrix断路器的功能。本节介绍此注解的原理

7.1 HystrixCommandAspect

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

HystrixCommandAspect的关键代码如下:

  • 1 方法 hystrixCommandAnnotationPointcut() 定义拦截注解HystrixCommand
  • 2 方法 hystrixCollapserAnnotationPointcut()定义拦截注解HystrixCollapser
  • 3 方法methodsAnnotatedWithHystrixCommand(…)通过@Around(…)拦截所有HystrixCommand和HystrixCollapser注解的方法。详细见方法注解
@Aspect
public class HystrixCommandAspect { @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 method = getMethodFromTarget(joinPoint);
Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
// 只有被HystrixCommand和HystrixCollapser注解的方法才执行后续操作
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");
}
// 根据拦截方法的注解HystrixCommand或HystrixCollapser分别获取CommandMetaHolderFactory或者CollapserMetaHolderFactory类
MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
// 将拦截方法封装到MetaHolder中
MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
// 根据metaHolder生成相应的HystrixCommand,包含生成hystrix执行时需要的配置信息,这些配置信息来自默认配置或我们自定义的属性
HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);
ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType(); Object result;
try {
// 根据是否是Observable执行CommandExecutor.execute()方法,executeObservable最后也会执行CommandExecutor.execute()方法
if (!metaHolder.isObservable()) {
result = CommandExecutor.execute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
} catch (HystrixBadRequestException e) {
throw e.getCause() != null ? e.getCause() : e;
} catch (HystrixRuntimeException e) {
throw hystrixRuntimeExceptionToThrowable(metaHolder, e);
}
return result;
} ….
}

@EnableCircuitBreaker 和 EnableCircuitBreakerImportSelector

那么谁来触发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的原理

Spring cloud Hystrix使用@HystrixCommand使用Hystrix组件及@EnableCircuitBreaker原理介绍的更多相关文章

  1. Spring Cloud(五):Hystrix 监控面板【Finchley 版】

    Spring Cloud(五):Hystrix 监控面板[Finchley 版]  发表于 2018-04-16 |  更新于 2018-05-10 |  在上一篇 Hystrix 的介绍中,我们提到 ...

  2. Spring Cloud(六):Hystrix 监控数据聚合 Turbine【Finchley 版】

    Spring Cloud(六):Hystrix 监控数据聚合 Turbine[Finchley 版]  发表于 2018-04-17 |  更新于 2018-05-07 |  上一篇我们介绍了使用 H ...

  3. Hadoop基础-Hdfs各个组件的运行原理介绍

    Hadoop基础-Hdfs各个组件的运行原理介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.NameNode工作原理(默认端口号:50070) 1>.什么是NameN ...

  4. 玩转Spring Cloud之熔断降级(Hystrix)与监控

    本文内容导航目录: 前言:解释熔断降级一.搭建服务消费者项目,并集成 Hystrix环境 1.1.在POM XML中添加Hystrix依赖(spring-cloud-starter-netflix-h ...

  5. spring cloud 系列第5篇 —— hystrix+turbine 服务的熔断与监控 (F版本)

    源码Gitub地址:https://github.com/heibaiying/spring-samples-for-all 一.hystrix 简介 1.1 熔断器 在分布式系统中,由于服务之间相互 ...

  6. Spring Cloud (7) 服务容错保护-Hystrix服务降级

    在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以互相调用,在Spring Cloud可以用RestTemplate+Ribbon和Feign来调用.为了保证其高可用,单个服务通常会集群 ...

  7. 【Spring Cloud学习之六】断路器-Hystrix

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 一.服务雪崩1.什么是服务雪崩分布式系统中经常会出现某个基础服务不可用造成整个系统不 ...

  8. Spring Cloud(4):断路器(Hystrix)

    Hystrix介绍 相对于单一系统,分布式系统更容易遇到故障,所以我们一般通过构建冗余,使用集群和负载均衡来保证系统的弹性和高可用.当然,这种方式只解决了一部分问题,当服务崩溃时,我们很容易检测到,因 ...

  9. spring cloud学习笔记四 熔断器Hystrix

    我们知道分布式服务有这样一个特点,每一个微服务都有自己的业务,并且很多时候一个微服务的业务要依赖于其他微服务,如果这些相互关联的微服务中其中某个微服务请求失败时,就会导致其他调用它的微服务也会请求失败 ...

随机推荐

  1. JavaScript变量: 变量命名原则

    变量的命名相对而言没有太多的技术含量,今天整理有关于变量命名相关的原则,主要是想告诉大家,虽然命名没有技术含量,但对于个人编码,或者说一个团队的再次开发及阅读是相当有用的.良好的书写规范可以让你的Ja ...

  2. bzoj1069: [SCOI2007]最大土地面积 凸包+旋转卡壳求最大四边形面积

    在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成的多边形面积最大. 题解:先求出凸包,O(n)枚举旋转卡壳,O(n)枚举另一个点,求最大四边形面积 /* ...

  3. oracle表的统计信息完全正确,执行计划无故改变。原厂人员如是回复

    就像在电话里提到的那样,Oracle内部的优化器是根据一系列的内部算法基于表上的统计信息来产生执行计划的.对于特别复杂的SQL语句,Oracle的优化器有一定几率不能得到最优的执行计划(因为机器代码实 ...

  4. 关于 XML 头声明和standalone 的解释

    <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <roo ...

  5. POJ 3087 Shuffle'm Up 线性同余,暴力 难度:2

    http://poj.org/problem?id=3087 设:s1={A1,A2,A3,...Ac} s2={Ac+1,Ac+2,Ac+3,....A2c} 则 合在一起成为 Ac+1,A1,Ac ...

  6. 201621123010《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词. 继承extends.多态.抽象类 超级父类Object类.父类.子类. 覆盖Override 初始化块 识别类 重载 1.2 ...

  7. block 回调个人理解

    在网上见过这么个面试题 使用block和GCD时要注意些什么?他们是一回事吗?block在ARC和MRC的用法有什么不同?使用时要注意些什么? 首先block 和 GCD 在我看来他们是完全不同的概念 ...

  8. java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout

    java.lang.AbstractMethodError: org.mybatis.spring.transaction.SpringManagedTransaction.getTimeout()L ...

  9. [转载]队列queue和双端Dequeue

    转载自:http://uule.iteye.com/blog/2095650?utm_source=tuicool 注意:这都只是接口而已 1.Queue API 在java5中新增加了java.ut ...

  10. HDU 3986

    http://acm.hdu.edu.cn/showproblem.php?pid=3986 从开始的最短路里依次删一条边,求新的最短路,求最长的最短路 删边操作要标记节点以及节点对应的边 #incl ...