spring-cloud源码解析-hystrix的基本介绍和配置属性说明


声明:本文转载自https://my.oschina.net/dengfuwei/blog/1621342,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

Hystrix简单介绍


  • Hystrix是一个延迟和容错库,目的是用来隔离远程系统、服务和第三方库的调用以及停止故障传播,并在无法完全避免发生故障的复杂的分布式系统中实现弹性

  • Hystrix主要的作用

    • 隔离(线程隔离、信号量隔离):主要是限制调用分布式服务的资源,避免个别服务出现问题时对其他服务产生影响

    • 熔断(容错):当失败率达到一定阈值时,熔断器触发快速失败

    • 降级(超时降级、熔断降级):触发降级时可以使用回调方法返回托底数据

    • 缓存:请求缓存、请求合并

    • 实时监控、报警

  • 源码地址:https://github.com/Netflix/Hystrix

spring cloud整合Hystrix基本使用


  • 引入maven依赖
<dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency> 
  • 在启动类上增加注解@EnableCircuitBreaker或@EnableHystrix(此注解引入了@EnableCircuitBreaker)

  • 在需要使用熔断降级的方法上增加注解,并配置降级方法

package com.itopener.demo.hystrix.client.service;  import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service;  import com.itopener.framework.ResultMap; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;  @Service public class HystrtixService { 	 	private final Logger logger = LoggerFactory.getLogger(HystrtixService.class);  	/** 	 * @description HystrixCommand注解默认超时时间是1s 	 * 		HystrixCommand注解配置属性参见 {@code HystrixCommandProperties} 	 * @author fuwei.deng 	 * @date 2018年2月8日 下午5:02:22 	 * @version 1.0.0 	 * @param id 	 * @return 	 */ 	@HystrixCommand(fallbackMethod = "callFallback") 	public ResultMap call(long id){ 		try { 			Thread.sleep(5000); 		} catch (Exception e){ 			logger.error("sleep exception ", e); 		} 		return ResultMap.buildSuccess(); 	} 	 	public ResultMap callFallback(long id){ 		return ResultMap.buildFailed("hystrix fallback : " + id);     } } 

Hystrix部分源码解析


spring cloud是基于spring boot开发的,可以由spring-cloud-starter-hystrix作为入口查看依赖的包

spring-cloud-starter-hystrix依赖包

其中,hystrix开头的是Hystrix原本的jar包,所以查看spring-cloud-netflix-core包中

spring-cloud-netflix-core中hystrix类

主要有两个配置类:HystrixAutoConfiguration、HystrixCircuitBreakerConfiguration。其中HystrixAutoConfiguration主要是hystrix的健康检查的配置,主要配置在HystrixCircuitBreakerConfiguration中,从里面加载的bean名称可以看到Hystrix的处理入口是:HystrixCommandAspect

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

HystrixCommandAspect这个类利用AOP切面对 HystrixCommandHystrixCollapser 两种注解的方法进行扩展处理。下面是截取的部分代码

/**  * AspectJ aspect to process methods which annotated with {@link HystrixCommand} annotation.  */ @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 {             if (!metaHolder.isObservable()) {                 result = CommandExecutor.execute(invokable, executionType, metaHolder);             } else {                 result = executeObservable(invokable, executionType, metaHolder);             }         } catch (HystrixBadRequestException e) {             throw e.getCause();         } catch (HystrixRuntimeException e) {             throw hystrixRuntimeExceptionToThrowable(metaHolder, e);         }         return result;     } } 

这里简单介绍下两种注解的配置

  • HystrixCommand

用于标记需要命令模式处理的方法

package com.netflix.hystrix.contrib.javanica.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;   /**  * 用于标记使用Hystrix命令模式执行的方法  */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface HystrixCommand {      /**      * 命令模式分组key,用于将如报表,告警,仪表板或团队/库所有权分组,默认值是类名      */     String groupKey() default "";      /**      * 命令的key值,默认值是方法名      */     String commandKey() default "";      /**      * 线程池key,用于表示HystrixThreadPool,用于监视,度量标准发布,缓存和其他此类用途.      */     String threadPoolKey() default "";      /**      * 执行降级回调方法,指定的方法必须和注解方法在同一个类中,并且必须和注解方法有相同的方法签名      */     String fallbackMethod() default "";      /**      * 配置命令模式的参数,具体参数对应类:HystrixCommandProperties      */     HystrixProperty[] commandProperties() default {};      /**      * 配置线程池参数,具体参数对应类:HystrixThreadPoolProperties      */     HystrixProperty[] threadPoolProperties() default {};      /**      * 定义需要忽略的异常。如果方法抛出的异常包含RUNTIME_EXCEPTION,会被包装成HystrixRuntimeException。具体逻辑在HystrixCommandAspect的hystrixRuntimeExceptionToThrowable方法      */     Class<? extends Throwable>[] ignoreExceptions() default {};      /**      * 定义观察者命令执行方式,详细说明见ObservableExecutionMode。判断逻辑在CommandExecutor.execute方法中      */     ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;      /**      * 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。此方法定义需要抛出的异常      */     HystrixException[] raiseHystrixExceptions() default {};      /**      * 默认降级回调方法,配置的方法不能有参数,返回值需要与注解的返回值兼容      */     String defaultFallback() default ""; } 
  • HystrixCollapser

这个注解需要和HystrixCommand注解配合使用。主要是用来做请求合并的,可以指定在某段时间内(默认10毫秒)调用此方法时会合并到一起执行。源码中有详细注释和示例,贴出来的进行了一部分翻译

package com.netflix.hystrix.contrib.javanica.annotation; import com.netflix.hystrix.HystrixCollapser.Scope;  import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;  /**  * 此注解用来将一些命令合并成单个后端依赖关系调用  * 此注解需要与{@link HystrixCommand}注解一起使用  * <p/>  * 示例:  * <pre>  *    @HystrixCollapser(batchMethod = "getUserByIds"){  *        public Future<User> getUserById(String id) {  *        return null;  *    }  *    @HystrixCommand  *    public List<User> getUserByIds(List<String> ids) {  *        List<User> users = new ArrayList<User>();  *        for (String id : ids) {  *            users.add(new User(id, "name: " + id));  *        }  *        return users;  *    }  *</pre>  *  * 使用{@link HystrixCollapser}注解的方法可以返回任何兼容的类型,返回结果并不影响合并请求的执行,甚至可以返回{@code null}或者其他子类  * 需要注意的是:注解的方法如果返回Future类型,那么泛型必须和命令方法返回的List泛型一致  * 例如:  * <pre>  *     Future<User> - {@link HystrixCollapser}注解方法返回值  *     List<User> - 批量命令方法返回值  * </pre>  * <p/>  * 注意:批量命令方法必须用{@link HystrixCommand}注解标记  */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface HystrixCollapser {      /**      * 指定一个key,默认值是注解方法名      */     String collapserKey() default "";      /**      * 批量命令方法的名称,指定的方法必须有如下的签名      *     java.util.List method(java.util.List)      * 注意:指定的方法只能有一个参数      */     String batchMethod();      /**      * 指定合并请求的范围默认是{@link Scope#REQUEST}      */     Scope scope() default Scope.REQUEST;      /**      * 指定合并请求的配置,具体参见{@link HystrixCollapserProperties}      */     HystrixProperty[] collapserProperties() default {};  } 

配置方式和属性说明


Hystrix的配置借助了Archaius来初始化,Archaius用于动态管理属性配置,是对apache common configuration类库的扩展。可以事先将多环境多个配置加载进去,支持定时刷新(线程安全),需要属性时可以直接获取。Archaius的配置类是ArchaiusAutoConfiguration,这里主要介绍一些属性的意思

还需要说明的是,属性配置可以是在properties文件中,也可以是在方法注解的属性里配置,两处配置的属性名称有区别,在properties里配置的属性是以 hystrix.command.default.hystrix.threadpool.defaulthystrix.collapser.default 开头,其中default表示默认值,如需要配置指定commandKey的值,将default换成commandKey即可。如果是在方法注解的属性里配置,则不需要这个前缀

  • HystrixCommandProperties
/**  * Command execution properties.  */ # 隔离策略,默认是线程隔离,还有信号量隔离,参见枚举:ExecutionIsolationStrategy hystrix.command.default.execution.isolation.strategy=THREAD # 隔离线程超时时间,默认1s hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000 # 是否启用超时配置 hystrix.command.default.execution.timeout.enabled=true # 超时的时候是否中断隔离线程 hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true # 隔离线程正在执行取消操作时是否中断 hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel=false # 隔离策略的最大信号量,只有使用信号量隔离策略时生效 hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=10  /**  * Command fallback properties.HystrixCommand.getFallback()  */ # 降级方法的最大调用线程数,如果超出此信号量,会抛出异常 hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests=10 # 是否启用降级 hystrix.command.default.fallback.enabled=true  /**  * Command circuit breaker properties.  */ # 是否启用断路器 hystrix.command.default.circuitBreaker.enabled=true # 请求量阈值,请求量达到该值是会开启断路器 hystrix.command.default.circuitBreaker.requestVolumeThreshold=20 # 当断路器打开后,会直接拒绝请求,此时间是配置多长时候后再次尝试处理请求 hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000 # 打开断路器并走回退逻辑的错误率,默认50% hystrix.command.default.circuitBreaker.errorThresholdPercentage=50 # 是否强制打开断路器,打开后会直接拒绝所有请求 hystrix.command.default.circuitBreaker.forceOpen=false # 是否强制关闭断路器,关闭后会处理所有请求 hystrix.command.default.circuitBreaker.forceClosed=false  /**  * Command metrics properties.主要用于统计执行情况  */ # 统计的时间窗口值 hystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000 # 统计时间窗口内分成的份数,需要保证timeInMilliseconds % numBuckets == 0 hystrix.command.default.metrics.rollingStats.numBuckets=10 # 是否启用百分数统计 hystrix.command.default.metrics.rollingPercentile.enabled=true # 百分数统计的时间周期 hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds=60000 # 百分数统计时间内分成的份数 hystrix.command.default.metrics.rollingPercentile.numBuckets=6 # 百分数统计每份的最大数量。每个bucket只取这个配置数量的执行数来统计 hystrix.command.default.metrics.rollingPercentile.bucketSize=100 # 记录健康快照间隔毫秒数 hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds=500  /**  * Command CommandRequest Context properties.  */ # 是否启用请求缓存。当HystrixCommand.getCacheKey()调用后,缓存到HystrixRequestCache hystrix.command.default.requestCache.enabled=true # 是否启用请求日志记录。HystrixCommand执行或者事件的日志到HystrixRequestLog hystrix.command.default.requestLog.enabled=true 
  • HystrixThreadPoolProperties
/**  * Thread pool properties.  */ # 是否启用maximumSize配置 hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize=false # 线程数量 hystrix.threadpool.default.coreSize=10 # 最大执行线程数 hystrix.threadpool.default.maximumSize=10 # 线程存活毫秒数 hystrix.threadpool.default.keepAliveTimeMinutes=1 # 最大等待线程队列,如果-1为SynchronousQueue;其他则为LinkedBlockingQueue hystrix.threadpool.default.maxQueueSize=-1 # 拒绝队列大小,即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝。当maxQueueSize为-1,则该属性不可用 hystrix.threadpool.default.queueSizeRejectionThreshold=5 # 线程池统计时间窗口值 hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds=10000 # 线程池统计时间窗口内分成的份数 hystrix.threadpool.default.metrics.rollingStats.numBuckets=10 
  • HystrixCollapserProperties
/**  * Collapser properties.  */ # 批处理最大请求数,达到该值时就算没有达到时间也会触发批处理,默认值Integer.MAX_VALUE hystrix.collapser.default.maxRequestsInBatch=0x7fffffff # 触发批处理的延迟,在触发之前的同样请求可能会放到同一个批处理中 hystrix.collapser.default.timerDelayInMilliseconds=10 # 是否启用请求缓存 hystrix.collapser.default.requestCache.enabled=true # 统计时间窗口值 hystrix.collapser.default.metrics.rollingStats.timeInMilliseconds=10000 # 统计时间窗口内分成的份数 hystrix.collapser.default.metrics.rollingStats.numBuckets=10 # 是否启用百分数统计 hystrix.collapser.default.metrics.rollingPercentile.enabled=true # 百分数统计的时间周期 hystrix.collapser.default.metrics.rollingPercentile.timeInMilliseconds=60000 # 百分数统计时间内分成的份数 hystrix.collapser.default.metrics.rollingPercentile.numBuckets=6 # 百分数统计每份的最大数量。每个bucket只取这个配置数量的执行数来统计 hystrix.collapser.default.metrics.rollingPercentile.bucketSize=100 

参考资料


本文发表于2018年02月11日 18:36
(c)注:本文转载自https://my.oschina.net/dengfuwei/blog/1621342,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1714 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1