zoukankan      html  css  js  c++  java
  • 浑身尖刺的服务可用性守护者——hystrix熔断器实践记录

    netflix公司的产品hystrix(长满刺的豪猪),在高可用目标下具有一定熔断、限流、降级的作用。
    这里主要写一些自己在使用时的问题解决思路,原理请自行理解,包括线程池与信号量模式等。

    注意三个参数的默认值:

    1、commandGroup  默认为getClass().getSimpleName();

    2、commandKey  默认为getClass().getSimpleName()(继承HystrixCommand方式)/ 方法名(注解方式),可与commandGroup相同;

    3、threadPoolKey  默认与commandGroup相同,即一个group共用线程池。这个key也可以单独定义,原因是属于相同逻辑功能的“组”,其中每个命令占用的资源彼此之间可能需要隔离。


    hystrix在普通java项目中有两种应用方式,首先引入依赖
    <dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-core</artifactId>
    <version>1.5.12</version>
    </dependency>
    一、写一个类继承HystrixCommand,组合需要熔断的方法所在的接口或实现类,重写run()和getFallback(),
    run()中写业务调用原方法的逻辑,getFallback()中可以通过getFailedExecutionException()处理方法执行异常。
    在构造函数中通过super(Setter.xxx)配置参数。

    附:设置参数示例
    super(Setter
    .withGroupKey(
    HystrixCommandGroupKey.Factory.asKey(xxxWithCircuitBreaker.class.getName()))
    .andThreadPoolKey(
    HystrixThreadPoolKey.Factory.asKey(xxxWithCircuitBreaker.class.getName()))
    .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(5))// 服务线程池数量
    .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutEnabled(true)
    .withExecutionTimeoutInMilliseconds(1000)// 超时时间
    .withCircuitBreakerRequestVolumeThreshold(5)// 设置在一个滚动窗口中,打开断路器的最少请求数
    .withCircuitBreakerErrorThresholdPercentage(60)// 熔断器关闭到打开的百分比阈值
    .withCircuitBreakerSleepWindowInMilliseconds(5000)// 熔断器打开到关闭的时间窗长度
    ));

    外部使用hystrixCommand.execute();调用。
    注意:getFailedExecutionException()不包括超出withExecutionTimeoutInMilliseconds设置的时间时抛出的异常以及在熔断状态下调用方法时抛出的异常。
    通过阅读源码发现HystrixCommand这个方式可以做更多扩展,比如通过getExecutionException()方法获取方法执行中的所有异常,这里是自己在测试过程中简单的异常处理逻辑:
    Exception e = (Exception) getExecutionException();
    if (e instanceof HystrixTimeoutException) {
    logger.error("方法执行超时");
    } else if (e instanceof RuntimeException) {
    // 大部分原因是发生熔断阻断了方法请求
    logger.error(e.getMessage());
    } else if (null != getFailedExecutionException())
    logger.error("方法执行异常", getFailedExecutionException());

    二、@HystrixCommand注解方式
    要额外引入一个依赖。
    <dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-javanica</artifactId>
    <version>1.5.12</version>
    </dependency>

    spring配置文件中加入aop:

    xmlns:aop="http://www.springframework.org/schema/aop"

    。。。

    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd

    。。。

    <aop:aspectj-autoproxy/>
    <bean id="hystrixAspect"
    class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"></bean>


    hystrix使用Netflix Archaius作为配置中心(这个东西可以动态变更配置),默认配置文件在resources下,名字为config.properties。
    如果需要指定配置文件位置,实践下来可以在项目启动过程中添加archaius所需的系统属性,如在spring监听器中添加。

    例:// 通过archaius配置hystrix全局参数
    System.setProperty("archaius.configurationSource.additionalUrls", "classpath:/properties/hystrix.properties");

    当然hystrix配置有四个优先级,这里是全局配置,如果没记错的话,配置文件中针对某commandKey的配置 优先于 方法注解中的配置 优先于 配置文件中全局配置。

    hystrix.properties示例内容(简单测试):
    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=100  注:timeoutInMilliseconds单位ms,可以设置到1,不知实际是否能精确到1ms,简单测试没啥问题。
    hystrix.command.default.circuitBreaker.requestVolumeThreshold=5
    hystrix.command.default.execution.isolation.strategy=THREAD

    这样在需要熔断的方法中只需指定相应fallback方法即可。
    @HystrixCommand(fallbackMethod = "fallback1")
    注解这里比继承HystrixCommand类的方式灵活的一点是可以在fallback方法中继续指定下一个fallback方法。
    但不便的一点是只能从getFailedExecutionException()查看异常,其已经作为fallback方法的Throwable e参数了。

    注意:

    1、如果进入fallback,Hystrix会默认打印出getFailedExecutionException()的异常堆栈信息,比如超时就不会打印。

    2、原则上fallback不允许抛出异常,但注解方式可以做到。Hystrix会打印如下两行加以提示。

    13:40:34.035 [hystrix-BulkIndexServiceImpl-1] ERROR c.n.h.contrib.javanica.command.GenericCommand - failed to process fallback is the method: 'fallback1'.
    13:40:34.038 [hystrix-BulkIndexServiceImpl-1] DEBUG com.netflix.hystrix.AbstractCommand - HystrixCommand execution COMMAND_EXCEPTION and fallback failed.

    3、注解可以通过定义参数成员ignoreExceptions = {CustomException.class}来定义无需进入fallback方法的异常(直接抛出,Hystrix算作成功执行,不会触发熔断),但是如果超时还是会进fallback。

    *4、个别情况下会发生run()方法和fallback()方法都成功执行完成,比如在测试时使用Thread.sleep() catch了InterruptedException,run()并未因超时而成功打断,在业务代码中应当注意try-catch问题,如果简单的catch Exception而catch之后仍有代码,则这些代码即时超时也会被执行。

    附:注解配置示例
    @HystrixCommand(groupKey = "hello", commandKey = "hello-service", threadPoolKey = "hello-pool", threadPoolProperties = {
    @HystrixProperty(name = "coreSize", value = "5") }, commandProperties = {
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
    @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "5"),
    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000")
    }, fallbackMethod = "fallback1")

    下篇mycat,欢迎交流指教。

  • 相关阅读:
    美国godaddy服务器,生成html网页出错,Microsoft VBScript runtime error '800a0005'
    Socket 错误一览表
    用php\asp创建 网页桌面快捷方式
    xp sp3 + ie8 支付宝证书 导入出错以及安全验证身份出错 解决办法
    Windows Server 2008正式版激活方法(2009年6月26日更新)
    子网掩码表示 255.255.255.0/24
    局域网中2台无线路由器联接配置方法
    firebug不能断点调试压缩后的js文件问题
    php正则匹配 <div></div>
    apache2 子目录forbidden问题
  • 原文地址:https://www.cnblogs.com/feixuefubing/p/10169940.html
Copyright © 2011-2022 走看看