前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >hystrix与dubbo整合及参数简介

hystrix与dubbo整合及参数简介

作者头像
山行AI
发布2019-06-28 11:58:54
2.1K1
发布2019-06-28 11:58:54
举报
文章被收录于专栏:山行AI山行AI

1. 配置部分

1. 引入maven依赖:

代码语言:javascript
复制
<dependency>
	<groupId>com.netflix.hystrix</groupId>
	<artifactId>hystrix-core</artifactId>
	<version>1.5.8</version>
</dependency>

2. 添加配置

在dubbo的spi加载filter的配置文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter中添加一行: HystrixFilter=com.rt.platform.infosys.base.common.filter.HystrixFilter

dubbo有着比较好的spi拓展点,如果用户需要自定义filter时,可以在这里添加,在dubbo启动时会自动加载。

2. 代码说明

1. HystrixFilter说明:

代码语言:javascript
复制
@Activate(group = Constants.CONSUMER)
public class HystrixFilter implements Filter {
  
    @Override  
    public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
        DubboHystrixCommand command = new DubboHystrixCommand(invoker, invocation);
        return command.execute();  
    }  
  
}  

2. DubboHystrixCommand代码说明:

代码语言:javascript
复制
public class DubboHystrixCommand extends HystrixCommand<Result> {

    private static final Logger LOGGER = LoggerFactory.getLogger(DubboHystrixCommand.class);

    private static final int DEFAULT_THREADPOOL_CORE_SIZE = 30;

    private Invoker invoker;

    private Invocation invocation;

    public DubboHystrixCommand(Invoker invoker, Invocation invocation) {

        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(invoker.getInterface().getName()))
                .andCommandKey(HystrixCommandKey.Factory.asKey(String.format("%s_%d", invocation.getMethodName(),
                        invocation.getArguments() == null ? 0 : invocation.getArguments().length)))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withCircuitBreakerRequestVolumeThreshold(300).withCircuitBreakerSleepWindowInMilliseconds(1000)// 熔断器中断请求1秒后会进入半打开状态,放部分流量过去重试
                        .withCircuitBreakerErrorThresholdPercentage(50)// 错误率达到50开启熔断保护
                        .withExecutionTimeoutEnabled(false))// 使用dubbo的超时,禁用这里的超时
                .andThreadPoolPropertiesDefaults(
                        HystrixThreadPoolProperties.Setter().withCoreSize(getThreadPoolCoreSize(invoker.getUrl()))
                                .withMaxQueueSize(1000).withQueueSizeRejectionThreshold(700)));// 线程池为30
        this.invoker = invoker;
        this.invocation = invocation;
    }

    /**
     * 获取线程池大小
     *
     * @param url
     * @return
     */
    private static int getThreadPoolCoreSize(URL url) {
        if (url != null) {
            int size = url.getParameter("ThreadPoolCoreSize", DEFAULT_THREADPOOL_CORE_SIZE);
            LOGGER.debug("======ThreadPoolCoreSize is:" + size);
            return size;
        }
        return DEFAULT_THREADPOOL_CORE_SIZE;
    }

    @Override
    protected Result run() throws Exception {
        return invoker.invoke(invocation);
    }

    @Override
    protected Result getFallback() {
        LOGGER.error("come into fall back method,please check it!",getFailedExecutionException());
        LOGGER.error("the execution exception is here!",getExecutionException());
        return new RpcResult(ResultFactory.failure(PublicExceptionCodeEnum.EX_SYS_BUSY.getCode(),
                PublicExceptionCodeEnum.EX_SYS_BUSY.getMsg()));
    }
  • hystrix的熔断机制有两种,一种是线程池隔离,一种是信号量模式。可以根据实际需求来使用对应的模式,这里使用的是线程池隔离来对dubbo服务调用进行保护。
  • 这里是用hystrix来保护dubbo的consumer,如果需要保护provider只需进行相应的配置即可,同时也可以用hystrix来保护一些昂贵的资源比如redis等。
  • 本篇文章着重介绍hystrix与dubbo的整合部分,关于hystrix的滑动窗口原理以及hystrix与sentinel的对比和怎样从hystrix平滑迁移到sentinel中去,请关注之后的文章。

3. hystrix配置参数说明:

1. default配置项(有默认值,也可配置)

  • commandKey:用来标识一个 Hystrix 命令,默认会取被注解的方法名。需要注意:Hystrix 里同一个键的唯一标识并不包括 groupKey,建议取一个独一二无的名字,防止多个方法之间因为键重复而互相影响。
  • groupKey:一组Hystrix命令的集合,用来统计、报告,默认取类名,可不配置。
  • threadPoolKey:用来标识一个线程池,如果没设置的话会取 groupKey,很多情况下都是同一个类内的方法在共用同一个线程池,如果两个共用同一线程池的方法上配置了同样的属性,在第一个方法被执行后线程池的属性就固定了,所以属性会以第一个被执行的方法上的配置为准。
  • commandProperties:与此命令相关的属性。
  • threadPoolProperties:与线程池相关的属性,
  • observableExecutionMode:我们常见的命令都是同步执行的,此配置项可以不配置。
  • ignoreExceptions:默认 Hystrix 在执行方法时捕获到异常时执行回退,并统计失败率以修改熔断器的状态,而被忽略的异常则会直接抛到外层,不会执行回退方法,也不会影响熔断器的状态。
  • raiseHystrixExceptions:当配置项包括 HystrixRuntimeException 时,所有的未被忽略的异常都会被包装成 HystrixRuntimeException,配置其他种类的异常好像并没有什么影响。
  • fallbackMethod:方法执行时熔断、错误、超时时会执行的回退方法,需要保持此方法与 Hystrix 方法的签名和返回值一致。
  • defaultFallback:默认回退方法,当配置 fallbackMethod 项时此项没有意义,另外,默认回退方法不能有参数,返回值要与 Hystrix方法的返回值相同。
1. commandProperties

线程隔离(Isolation)

  • execution.isolation.strategy: 隔离策略,有threadPool和semaphore两种,其中默认策略和线程池,也是比较常用的方式。
  • execution.timeout.enabled:是否给方法执行设置超时,默认为 true。
  • execution.isolation.thread.timeoutInMilliseconds:方法执行超时时间,默认值是 1000,即 1秒,此值根据业务场景配置。
  • execution.isolation.thread.interruptOnTimeout: execution.isolation.thread.interruptOnCancel:是否在方法执行超时/被取消时中断方法。需要注意在 JVM 中我们无法强制中断一个线程,如果 Hystrix 方法里没有处理中断信号的逻辑,那么中断会被忽略。
  • execution.isolation.semaphore.maxConcurrentRequests:默认值是 10,此配置项要在 execution.isolation.strategy 配置为 semaphore 时才会生效,它指定了一个 Hystrix 方法使用信号量隔离时的最大并发数,超过此并发数的请求会被拒绝。信号量隔离的配置就这么一个,也是前文说信号量隔离配置不灵活的原因。

统计器(Metrics) 基于滑动窗口和桶来实现。滑动窗口相当于一个时间窗,在这个时间窗中会有很多请求进入,如果每进入一个请求就统计一次这个时间窗的请求总数会有较低的性能,所以将这个时间窗口分成 十份,每份是一个桶,时间窗滑动到每个桶结束点时就统计一下这个桶内的请求数,就可以统计出整个窗口的请求数了。bucket(桶)一般是窗口的N分之一。

  • metrics.rollingStats.timeInMilliseconds:此配置项指定了窗口的大小,单位是 ms,默认值是 1000,即一个滑动窗口默认统计的是 1s 内的请求数据。
  • metrics.healthSnapshot.intervalInMilliseconds:它指定了健康数据统计器(影响 Hystrix 熔断)中每个桶的大小,默认是 500ms,在进行统计时,Hystrix通过 metrics.rollingStats.timeInMilliseconds / metrics.healthSnapshot.intervalInMilliseconds 计算出桶数,在窗口滑动时,每滑过一个桶的时间间隔时就统计一次当前窗口内请求的失败率。
  • metrics.rollingStats.numBuckets:Hystrix 会将命令执行的结果类型都统计汇总到一块,给上层应用使用或生成统计图表,此配置项即指定了,生成统计数据流时滑动窗口应该拆分的桶数。此配置项最易跟上面的 metrics.healthSnapshot.intervalInMilliseconds 搞混,认为此项影响健康数据流的桶数。 此项默认是 10,并且需要保持此值能被 metrics.rollingStats.timeInMilliseconds 整除。
  • metrics.rollingPercentile.enabled:是否统计方法响应时间百分比,默认为 true 时,Hystrix 会统计方法执行的 1%,10%,50%,90%,99% 等比例请求的平均耗时用以生成统计图表。
  • metrics.rollingPercentile.timeInMilliseconds:统计响应时间百分比时的窗口大小,默认为 60000,即一分钟。
  • metrics.rollingPercentile.numBuckets:统计响应时间百分比时滑动窗口要划分的桶用,默认为6,需要保持能被metrics.rollingPercentile.timeInMilliseconds整除。
  • metrics.rollingPercentile.bucketSize:统计响应时间百分比时,每个滑动窗口的桶内要保留的请求数,桶内的请求超出这个值后,会覆盖最前面保存的数据。默认值为 100,在统计响应百分比配置全为默认的情况下,每个桶的时间长度为 10s = 60000ms / 6,但这 10s内只保留最近的100条请求的数据。

熔断器(Circuit Breaker)

  • circuitBreaker.enabled:是否启用熔断器,默认为 true;
  • circuitBreaker.forceOpen: circuitBreaker.forceClosed:是否强制启用/关闭熔断器,强制启用关闭都想不到什么应用的场景,保持默认值,不配置即可。
  • circuitBreaker.requestVolumeThreshold:启用熔断器功能窗口时间内的最小请求数。试想如果没有这么一个限制,我们配置了 50% 的请求失败会打开熔断器,窗口时间内只有 3 条请求,恰巧两条都失败了,那么熔断器就被打开了,5s 内的请求都被快速失败。此配置项的值需要根据接口的 QPS 进行计算,值太小会有误打开熔断器的可能,值太大超出了时间窗口内的总请求数,则熔断永远也不会被触发。建议设置为 QPS * 窗口秒数 * 60%。
  • circuitBreaker.errorThresholdPercentage:在通过滑动窗口获取到当前时间段内 Hystrix 方法执行的失败率后,就需要根据此配置来判断是否要将熔断器打开了。 此配置项默认值是 50,即窗口时间内超过 50% 的请求失败后会打开熔断器将后续请求快速失败。
  • circuitBreaker.sleepWindowInMilliseconds:熔断器打开后,所有的请求都会快速失败,但何时服务恢复正常就是下一个要面对的问题。熔断器打开时,Hystrix 会在经过一段时间后就放行一条请求,如果这条请求执行成功了,说明此时服务很可能已经恢复了正常,那么会将熔断器关闭,如果此请求执行失败,则认为服务依然不可用,熔断器继续保持打开状态。此配置项指定了熔断器打开后经过多长时间允许一次请求尝试执行,默认值是 5000。

其他配置

  • requestCache.enabled:是否启用请求结果缓存。默认是 true,但它并不意味着我们的每个请求都会被缓存。缓存请求结果和从缓存中获取结果都需要我们配置 cacheKey,并且在方法上使用 @CacheResult 注解声明一个缓存上下文。
  • requestLog.enabled:是否启用请求日志,默认为 true。
  • fallback.enabled:是否启用方法回退,默认为 true 即可。
  • fallback.isolation.semaphore.maxConcurrentRequests:回退方法执行时的最大并发数,默认是10,如果大量请求的回退方法被执行时,超出此并发数的请求会抛出 REJECTED_SEMAPHORE_FALLBACK 异常。

threadPoolProperties:

  • coreSize:核心线程池大小,默认为10,一般根据 QPS * 99% cost + redundancy count 计算得出。
  • allowMaximumSizeToDivergeFromCoreSize:是否允许线程池扩展到最大线程池数量,默认为 false;
  • maximumSize:线程池中线程的最大数量,默认值是 10,此配置项单独配置时并不会生效,需要启用 allowMaximumSizeToDivergeFromCoreSize 项。
  • maxQueueSize:作业队列的最大值,默认值为 -1,设置为此值时,队列会使用 SynchronousQueue,为同步队列,此时其 size 为0,Hystrix 不会向队列内存放作业。如果此值设置为一个正的 int 型,队列会使用一个固定 size 的 LinkedBlockingQueue,此时在核心线程池内的线程都在忙碌时,会将作业暂时存放在此队列内,但超出此队列的请求依然会被拒绝。
  • queueSizeRejectionThreshold:由于 maxQueueSize 值在线程池被创建后就固定了大小,如果需要动态修改队列长度的话可以设置此值,即使队列未满,队列内作业达到此值时同样会拒绝请求。此值默认是 5,所以有时候只设置了 maxQueueSize 也不会起作用。
  • keepAliveTimeMinutes:由上面的 maximumSize,我们知道,线程池内核心线程数目都在忙碌,再有新的请求到达时,线程池容量可以被扩充为到最大数量,等到线程池空闲后,多于核心数量的线程还会被回收,此值指定了线程被回收前的存活时间,默认为 2,即两分钟。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开发架构二三事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 配置部分
    • 1. 引入maven依赖:
      • 2. 添加配置
      • 2. 代码说明
        • 1. HystrixFilter说明:
          • 2. DubboHystrixCommand代码说明:
          • 3. hystrix配置参数说明:
            • 1. default配置项(有默认值,也可配置)
              • 1. commandProperties
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档