SpringcloudHystrix使⽤@HystrixCommand使⽤Hystrix组。。。通过@HystrixCommand注解实现在Spring Cloud使⽤Hystrix组件相关的⼯程
cloud-registration-center:注册中⼼
cloud-service-hystrix: 作为服务⽅的⼯程
cloud-consumer-hystrix:通过hystrix调⽤cloud-service-hystrix的接⼝
1.cloud-service-hystrix
作为服务⽅的⼯程,此⼯程⽐较简单,
只列出部分内容
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的接⼝
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
# port
server:
port: 12083
spring:
application:
# 本服务注册到注册到服务器的名称, 这个名称就是后⾯调⽤服务时的服务标识符
name: cloud-consumer-hystrix
eureka:
client:
serviceUrl:
# 服务器注册/获取服务器的zone
defaultZone: 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) {
ForEntity("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的线程池的⼤⼩,其他的配置见
# 配置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:配置中⼼地址:
启动⼯程cloud-service-hystrix的HystrixCloudServiceApplication的启动类
启动⼯程cloud-consumer-hystrix的HystrixSimpleCloudConsumerApplication的启动类
测试⼀
执⾏cloud-consumer-hystrix的调⽤cloud-service-hystrix服务的接⼝
在浏览器中运⾏URL:
返回:
"rsp: \"time 1511015252093 hystrix1: 434\""
测试⼆
停⽌cloud-service-hystrix服务
执⾏cloud-consumer-hystrix的调⽤cloud-service-hystrix服务的接⼝
在浏览器中运⾏URL:
返回:
"rsp: Execute raw fallback: access service fail , req= 1511103681411 reason = ption.HystrixTimeoutException"
说明fallback⽅法被执⾏了
测试三
修改l 中的hystrix的线程池的线程数量为0,
# 配置hystrix的参数
hystrix:
threadpool:
# default: 默认参数,作⽤的所有的hystrix的客户端
default:
coreSize: 0
重启cloud-service-hystrix和cloud-consumer-hystrix,
执⾏
提⽰执⾏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(ib.javanica.annotation.HystrixCommand)")
public void hystrixCommandAnnotationPointcut() {
}
@Pointcut("@annotation(ib.javanica.annotation.HystrixCollapser)")
public void hystrixCollapserAnnotationPointcut() {
}
@Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
// 获取拦截的Method
Method method = getMethodFromTarget(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_(HystrixPointcutType.of(method));
// 将拦截⽅法封装到MetaHolder中
MetaHolder metaHolder = ate(joinPoint);
/
springboot aop/ 根据metaHolder⽣成相应的HystrixCommand,包含⽣成hystrix执⾏时需要的配置信息,这些配置信息来⾃默认配置或我们⾃定义的属性
HystrixInvokable invokable = Instance().create(metaHolder);
ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ?
Object result;
try {
// 根据是否是Observable执⾏ute()⽅法,executeObservable最后也会执⾏ute()⽅法
if (!metaHolder.isObservable()) {
result = ute(invokable, executionType, metaHolder);
} else {
result = executeObservable(invokable, executionType, metaHolder);
}
} catch (HystrixBadRequestException e) {
Cause() != 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.cloudflix.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.cloudflix.hystrix.HystrixCircuitBreakerConfiguration),从⽽最终初始化HystrixCommandAspect 类,从⽽实现拦截HystrixCommand的功能
以上就是通过@EnableCircuitBreake可以开启Hystrix的原理
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论