精华内容
下载资源
问答
  • 2020-05-03 09:21:58

    一、Hystix是什么呢

    Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
    熔断器Hystrix是容错管理工具,作用是通过隔离、控制服务从而对延迟和故障提供更强大的容错能力,避免整个系统被拖垮。

    二、Hystix有什么作用呢

    复杂分布式架构通常都具有很多依赖,当一个应用高度耦合其他服务时非常危险且容易导致失败,这种失败很容易伤害服务的调用者,最后导致一个接一个的连续错误,应用本身就处在被拖垮的风险中,最后失去控制,就像在一个高流量的网站中,某个单一的后端一旦发生延迟,将会在数秒内导致所有应用资源被耗尽。
    当在系统高峰时期,大量对微服务的调用可能会堵塞远程服务器的线程池,如果这个线程池没有和主应用服务器的线程池隔离,就会导致整个服务器挂机。
    Hystrix使用自己的线程池,这样和主应用服务器线程池隔离,如果调用花费很长时间,就停止调用,不同的命令或命令组能够被配置使用他们各自的线程池,可以隔离不同的服务。

    三、Hystix的工作机制

    熔断机制的原理,像家里的电路熔断器,如果电路发生短路能立刻熔断电路,避免发生灾难。在分布式系统中应用这一模式之后,服务调用放可以自己进行判断某些服务反应慢或者存在大量超时的情况时,能够自动熔断,防止整个系统被拖垮。
    Hystrix可以实现弹性容错,当情况好转之后,可以自动重连。

    正常工作的

    更多相关内容
  • Hystix

    2020-01-07 16:53:07
    当某个服务阻塞时,大量客户线程就会消耗完Tomcat的链接,从而其他服务也不可使用。这个现象就是服务雪崩。解决方案有两种:服务降级和服务熔断。 服务降级是消费者端进行的,服务熔断的服务生产者进行的。...

    当某个服务阻塞时,大量客户线程就会消耗完Tomcat的链接,从而其他服务也不可使用。这个现象就是服务雪崩。解决方案有两种:服务降级和服务熔断。

    服务降级是消费者端进行的,服务熔断的服务生产者进行的。

    服务降级

    服务降级,就是服务超时后立刻返回给客户一个失败的信息,不让它在占用Tomcat的链接。

    1、导入jar

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

    2、yml

    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 3000  
    #配置服务降级的时长,不配置也可以,默认是1s,这里配置成了3s,这是全局的配置

    3、ConsumerController

    @RestController
    @RequestMapping("consumer")
    @DefaultProperties(defaultFallback = "defaultFallback") //默认的返回降级的方法
    public class ConsumerController {
        @Autowired
        private RestTemplate restTemplate;
        @GetMapping("{id}")
        //@HystrixCommand(fallbackMethod = "queryByIdFallback")//可以独立配置降级方法
        @HystrixCommand(commandProperties = {
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")//独立配置降级时间
        })
        public String queryById(@PathVariable("id") Long id) {
            String url="http://user-service/user/"+id;//ip+端口 用服务id代替了,默认是轮询
            String user = restTemplate.getForObject(url, String.class);
            return  user;
        }
    
        public String queryByIdFallback(Long id){
            return "服务太拥挤了";
        }
        public String defaultFallback(){
            return "默认服务太拥挤了";
        }

    服务熔断

    默认情况下,20次服务请求,50%的失败率就会触发服务熔断。此时熔断器就会打开,打开后5s后会进入半开状态,会允许少量的请求通过,测试服务是否可用,可用熔断器就会变为关闭状态,否则继续等5s继续测试。

    这个很难演示出来,所以用id模拟这个熔断。

    @RestController
    @RequestMapping("consumer")
    @DefaultProperties(defaultFallback = "defaultFallback")
    public class ConsumerController {
        @Autowired
        private RestTemplate restTemplate;
        @GetMapping("{id}")
        //@HystrixCommand(fallbackMethod = "queryByIdFallback")
        @HystrixCommand(commandProperties = {
                //请求次数不小于10次
                @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),
    //10s进入半开状态
    
    @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),
    //60%的错误熔断熔断器
    @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="60")
        })
        public String queryById(@PathVariable("id") Long id) {
            //抛出异常表明服务失败
            if(id%2==0){
                throw new RuntimeException("异常");
            }
            String url="http://user-service/user/"+id;//ip+端口 用服务id代替了,默认是轮询
            String user = restTemplate.getForObject(url, String.class);
            return  user;
        }
    
        public String queryByIdFallback(Long id){
            return "服务太拥挤了";
        }
        public String defaultFallback(){
            return "默认服务太拥挤了";
        }
    }
    

    开发状态下,这些参数不用调,这里为了演示效果。

    连续点击id为16的链接

    快速点击id为17的链接

    过几秒后再次点击id为17的链接

     它就又变好了。

    展开全文
  • 目录Hystix简介熔断器的工作机制入门案例测试优化 Hystix简介 Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。 熔断器的工作机制 在分布式系统中应用这一模式之后...

    Hystix简介

    • Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
      在这里插入图片描述

    熔断器的工作机制

    • 在分布式系统中应用这一模式之后,服务调用方可以自己进行判断某些服务反应慢或者存在大量超时的情况,能够主动熔断,防止整个系统被拖垮。
    • 演示大概:
      • 一开始的服务调用:
        在这里插入图片描述
      • 当有服务出现异常时,直接进行失败回滚,服务降级处理
        在这里插入图片描述
    • 当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。
    • 系统特别繁忙时,一些次要服务暂时中断,优先保证主要服务的畅通,一切资源优先让给主要服务来使用,在双十一、618时,京东天猫都会采用这样的策略,将一些不必要的功能关掉,提供给购物。

    入门案例

    1. 在服务调用者导入依赖
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    1. 在服务调用者的启动类上,引入标签@EnableCircuitBreaker
      在这里插入图片描述
      • 或者可以在服务调用者上直接使用@SpringCloudApplication
        在这里插入图片描述
        • ctrl+右键点击标签@SpringCloudApplication
          ,进入查看,发现跟之前的一样,也有那三个标签,所以只用写一个@SpringCloudApplication
          就好了。
          在这里插入图片描述
    2. 在调用函数上附上标签@HystrixCommand(fallbackMethod = "findByIdFallback"),并且创建Fallback函数
      • @HystrixCommand(fallbackMethod = "findByIdFallback"):声明一个失败回滚处理函数findByIdFallback,当qfindById执行超时(默认是1000毫秒),就会执行fallback函数,返回错误提示。
      • 注意:fallback函数必须跟主函数的返回和参数一样,不然会报错误。
        在这里插入图片描述
      • 如果每个方法的话,就需要创建多个fallback函数,所以只需要在类上加上标签@DefaultProperties(defaultFallback = "findByIdFallback")
        • 注意这个时候就不能有参数,因为这是全部方法的,所以他需要的空参的函数。
          在这里插入图片描述

    测试

    1. 修改服务提供者的service,让他沉睡2s
      在这里插入图片描述
    2. 启动测试
      在这里插入图片描述

    优化

    1. Ribbon的超时时间一定要小于Hystix的超时时间。
      • 假设我们的Ribbon超时时间设置的是1000ms,而Hystix的超时时间默认也是1000ms,导致重试机制没有被触发,而是先触发了熔断。
    2. 我们可以通过hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds来设置Hystrix超时时间。有两种方法
      • 第一种,在application.yml上配置
        • 其中default是默认所有的方法,如果你想要的是单一方法,可以修改成对应的,或是你想要的某个服务也可以
          在这里插入图片描述
      • 第二种,在方法上利用标签配置
        在这里插入图片描述
    展开全文
  • 此文为《Spring Cloud、Nginx高并发核心编程_尼恩 (作者) _机械工业出版社》 关于Hystix部分的读书笔记,不太清楚的地方又在网上另外找了资料 一、简介 RPC保护目标 在分布式多节点集群架构系统内部,在节点之间...

    此文为《Spring Cloud、Nginx高并发核心编程_尼恩 (作者) _机械工业出版社》 关于Hystix部分的读书笔记,不太清楚的地方又在网上另外找了资料 

    一、简介

    RPC保护目标

    在分布式多节点集群架构系统内部,在节点之间进行RPC保护的目标如下:

    1.避免整个系统出现级联失败而雪崩,这是非常重要的目标。

    在RPC调用过程中,需要防止由单个服务的故障而耗尽整个服务集群的线程资源,避免分布式环境里大量级联失败。

    2.RPC调用能够相互隔离。

    为每一个目标服务维护着一个线程池(或信号量),即使其中某个目标服务的调用资源被耗尽,也不会影响对其他服务的RPC调用。

    当目标服务的线程池(或信号量)被耗尽时,拒绝RPC调用。

    3.能够快速地降级和恢复。

    当RPC目标服务故障时,能够快速和优雅地降级;当RPC目标服务失效后又恢复正常时,快速恢复。

    4.能够对RPC调用提供接近实时的监控和警报。

    监控信息包括请求成功、请求失败、请求超时和线程拒绝。如果对特定服务RPC调用的错误百分比超过阈值,后续的RPC调用就会自动失败,一段时间内停止对该服务的所有请求。

    Spring Cloud在调用处理器中是使用HystrixCommand命令封装RPC调用,从而实现RPC保护。

    HystrixCommand

    Hystrix使用命令模式并结合RxJava的响应式编程和滑动窗口技术实现了对外部服务RPC调用的保护。

    Hystrix实现了HystrixCommandHystrixObservableCommand两个命令类,用于封装需要保护的RPC调用。

    HystrixObservableCommand命令不具备同步执行的能力,只具备异步执行能力,

    HystrixCommand命令即具备同步执行的能力有具备异步执行的能力,并且Spring Cloud中重点使用HystrixCommand命令,因此本篇将以HystrixCommand命令为重点介绍Hystrix的原理和使用。

    二、HystrixCommand的使用

    依赖

    如果不是在Spring Cloud的开发环境中使用HystrixCommand命令,就需要增加其Maven的依赖坐标

    <dependency>
     <groupId>com.netflix.hystrix</groupId>
     <artifactId>hystrix-core</artifactId>
    </dependency>

    独立使用HystrixCommand命令主要有以下两个步骤

    1.继承HystrixCommand类,

    将正常的业务逻辑实现在继承的run方法中,

    将回退的业务逻辑实现在继承的getFallback方法中。

    2.使用HystrixCommand类提供的启动方法启动命令的执行。

    使用HystrixCommand命令时,需要通过它的启动方法(如execute)来启动其执行(类似Thread通过start方法启动run方法的执行)

    例子

    下面通过继承HystrixCommand创建一个简单的HTTP请求命令,并且对HTTP请求过程中
    执行的总次数、失败的总次数进行统计,具体的代码如下:

    @Slf4j
    public class HttpGetterCommand extends HystrixCommand<String>
    {
         private String url;
         //run方法是否执行
         private boolean hasRun = false;
         //执行的次序
         private int index;
         //执行的总次数,线程安全
         private static AtomicInteger total = new AtomicInteger(0);
         //失败的总次数,线程安全
         private static AtomicInteger failed = new AtomicInteger(0);
         public HttpGetterCommand(String url, Setter setter){
            super(setter);
            this.url = url;
         }
         @Override
         protected String run() throws Exception{
            hasRun = true;
            index = total.incrementAndGet();
            log.info("req{} begin...", index);
            String responseData = HttpRequestUtil.simpleGet(url);
            log.info(" req{} end: {}", index, responseData);
            return "req" + index + ":" + responseData;
         }
         @Override
         protected String getFallback(){
             //是否直接失败
             boolean isFastFall = !hasRun;
             if (isFastFall){
                index = total.incrementAndGet();
             }
             if (super.isCircuitBreakerOpen()){
                HystrixCommandMetrics.HealthCounts hc = 
                super.getMetrics().getHealthCounts();
                log.info("window totalRequests:{},errorPercentage:{}",
                hc.getTotalRequests(), //滑动窗口总的请求数
                hc.getErrorPercentage()); //滑动窗口出错比例
             }
             //熔断器是否打开
             boolean isCircuitBreakerOpen = isCircuitBreakerOpen();
             log.info("req{} fallback: 熔断{},直接失败 {},失败次数{}",
             index,
             isCircuitBreakerOpen,
             isFastFall,
             failed.incrementAndGet());
             return "req" + index + ":调用失败";
         }
    }

    HttpGetterCommand的测试用例代码

    @Slf4j
    public class HystryxCommandExcecuteDemo
    {
     
         /***测试HttpGetterCommand */
         @Test
         public void testHttpGetterCommand() throws Exception{
    
         /**
         *构造配置实例
         */
         HystrixCommand.Setter setter = HystrixCommand.Setter
         .withGroupKey(HystrixCommandGroupKey.Factory.asKey("group-1"))
         .andCommandKey(HystrixCommandKey.Factory.asKey("command-1"))
         .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("threadPool-1"));
    
         /**测试HttpGetterCommand */
         // 在构造函数中,使用HystrixCommand.Setter配置实例对该基类的实例进行了初始化。
         String result =new HttpGetterCommand(HELLO_TEST_URL, setter).execute();
    
         log.info("result={}", result);
     }
    }

    用例中首先构造了一个配置实例setter,配置了非常基础的命令组Key(GroupKey)、命令Key(CommandKey)、线程池Key(ThreadPoolKey)3个配置项,

    然后创建了HttpGetterCommand实例并使用execute()执行该命令。

    HystrixCommand的配置内容和方式 

    使用HystrixCommand.Setter配置实例进行配置 

    也就是上面代码中的:

    HystrixCommand.Setter setter = HystrixCommand.Setter
         .withGroupKey(HystrixCommandGroupKey.Factory.asKey("group-1"))
         .andCommandKey(HystrixCommandKey.Factory.asKey("command-1"))
         .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("threadPool-1"));

    其中涉及以下3个配置项:

    1.CommandKey:该命令的名称。

    2.GroupKey:该命令属于哪一个组,以帮助我们更好地组织命令。

    3.ThreadPoolKey:该命令所属线程池的名称。

    相同的线程池名称会共享同一线程池,若不进行配置,则默认使用GroupKey作为线程池名称。

    除此之外,还可以通过HystrixCommand.Setter配置实例,整体设置一些其他的属性集合,如:

    1.CommandProperties:与命令执行相关的一些属性集,包括降级设置、熔断器的配置、隔离策略以及一些监控指标配置项等。

    2.ThreadPoolProperties:与线程池相关的一些属性集,包括线程池大小、排队队列的大小等。 

    配置的例子

    public class SetterDemo{
         public static HystrixCommand.Setter buildSetter(String groupKey,String commandKey,String threadPoolKey){
             /**
             *与命令执行相关的一些属性集
             */
             HystrixCommandProperties.Setter commandSetter =HystrixCommandProperties.Setter()
             //至少有3个请求,熔断器才达到熔断触发的次数阈值
             .withCircuitBreakerRequestVolumeThreshold(3)
             //熔断器中断请求5秒后会进入half-open状态,尝试放行
             .withCircuitBreakerSleepWindowInMilliseconds(5000)
             //错误率超过60%,快速失败
             .withCircuitBreakerErrorThresholdPercentage(60)
             //启用超时
             .withExecutionTimeoutEnabled(true)
             //执行的超时时间,默认为1000ms
             .withExecutionTimeoutInMilliseconds(5000)
             //可统计的滑动窗口内的buckets数量,用于熔断器和指标发布
             .withMetricsRollingStatisticalWindowBuckets(10)
             //可统计的滑动窗口的时间长度
             //这段时间内的执行数据用于熔断器和指标发布
             .withMetricsRollingStatisticalWindowInMilliseconds(10000);
     
             /**
             *线程池配置
             */
             HystrixThreadPoolProperties.Setter poolSetter =
             HystrixThreadPoolProperties.Setter()
             //这里我们设置了线程池大小为5
             .withCoreSize(5)
             .withMaximumSize(5);
             /**
             *与线程池相关的一些属性集
             */
             HystrixCommandGroupKey hGroupKey = HystrixCommandGroupKey.Factory.
            asKey(groupKey);
             HystrixCommandKey hCommondKey = HystrixCommandKey.Factory.
            asKey(commandKey);
             HystrixThreadPoolKey hThreadPoolKey = HystrixThreadPoolKey.Factory.
            asKey(threadPoolKey);
             HystrixCommand.Setter outerSetter = HystrixCommand.Setter
             .withGroupKey(hGroupKey)
             .andCommandKey(hCommondKey)
             .andThreadPoolKey(hThreadPoolKey)
             .andCommandPropertiesDefaults(commandSetter)
             .andThreadPoolPropertiesDefaults(poolSetter);
             return outerSetter;
         }
    }

    使用Hystrix提供的ConfigurationManager配置管理类的工厂实例对HystrixCommand命令的执行参数进行配置

    //熔断器的请求次数阈值:大于3次请求
     ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.requestVolumeThreshold", 3);

    Spring Cloud Hystrix所使用的正是这种配置方法

    三、HystrixCommand命令的执行方法

    HystrixCommand提供了4个执行启动的方法:

    execute()

    以同步堵塞方式执行run()。

    一旦开始执行该命令,当前线程就会阻塞,直到该命令返回结果,然后才能继续执行下面的逻辑。

    实际上在内部使用queue().get()的方式完成同步调用的

    queue()

    异步非阻塞方式执行run()方法,该方法直接返回一个Future对象。

    可通过Future.get()拿到run()的返回结果,但Future.get()是阻塞执行的

    observe()

    返回一个响应式编程Observable主题(这是一个热主题(Hot Observable)),可以为该主题对象注册上Subscriber观察者回调实例,或者注册上Action1不完全回调实例来响应式处理命令的执行结果。

    如果HystrixCommand的run()方法执行成功,就会触发订阅者的onNext()和onCompleted()回调方法,如果执行异常,就会触发订阅者的onError()回调方法。

    什么是热主题呢?

    就是无论主题是否存在观察者订阅,都会自动触发执行它的run()方法。

    另外还有一点,observe()方法所返回的主题可以重复订阅

    toObservable()

    返回一个响应式编程Observable主题。

    同样可以为该主题对象注册上Subscriber观察者回调实例,或者注册上Action1不完全回调实例,来响应式处理命令的执行结果。

    不过,与observe()返回的主题不同,toObservable主题返回的是冷主题,并且只能被订阅一次

    什么是冷主题(Cold Observable)?

    就是在获取主题的时候不会立即触发执行,只有在观察者订阅时才会执行内部的HystrixCommand命令的run()方法。

     四、HystrixCommand命令的执行流程

    简单的流程图

    在获取HystrixCommand命令的执行结果时,无论是使用execute()、toObservable()方法,还是使用observe()方法,最终都会通过执行HystrixCommand.toObservable()订阅执行结果和返回。

    在Hystrix内部,调用toObservable()方法返回一个观察的主题,当Subscriber订阅者订阅主题后,HystrixCommand会弹射一个事件,然后通过一系列的判断,顺序依次是缓存是否命中、熔断器是否打开、线程池是否占满,开始执行实际的HystrixCommand.run()方法。

    该方法的实现主要为异步处理的业务逻辑,如果在这其中任何一个环节出现错误或者抛出异常,就会回退到getFallback()方法进行服务降级处理,当降级处理完成之后,会将结果返回给实际的调用者。

    HystrixCommand的工作流程总结

    1.判断是否使用缓存响应请求,若启用了缓存,且缓存可用,则直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动。

    2.判断熔断器是否开启,如果熔断器处于open状态,则跳到第5步。

    3.若使用线程池进行请求隔离,则判断线程池是否已占满,若已满则跳到第5步;若使用信号量进行请求隔离,则判断信号量是否耗尽,若耗尽则跳到第5步。

    4.使用HystrixCommand.run()方法执行具体业务逻辑,如果执行失败或者超时,就跳到第5步,否则跳到第6步。

    5.执行HystrixCommand.getFallback()服务降级处理逻辑。

    6.返回请求响应。 

    什么场景下会触发fallback方法呢?

     

    五、RPC保护之舱壁模式

    1.什么是舱壁模式

    船舶工业为了使船不容易沉没,使用舱壁将船舶划分为几个部分,以便在船体破坏的情况下可以将船舶各个部分密封起来。

    在RPC调用过程中,使用舱壁模式可以保护有限的系统资源不被耗尽。

    在一个基于微服务的应用程序中,通常需要调用多个服务提供者的接口才能完成一个特定任务。

    不使用舱壁模式,所有的RPC调用都从同一个线程池中获取线程,一个具体的实例如图所示。

    在该实例中,服务提供者Provider A对依赖的Provider B、Provider C、Provider D的所有RPC调用都从公共的线程池获取线程。

    在高服务器请求的情况下,对某个性能较低的服务提供者的RPC调用很容易“霸占”整个公共的RPC线程池,对其他性能正常的服务提供者的RPC调用往往需要等待线程资源的释放。最后,整个Web容器(Tomcat)会崩溃。

    为了最大限度地减少Provider之间的相互影响,一个更好的做法是:

    对于不同的服务提供者可以设置不同的RPC调用线程池,让不同RPC通过专门的线程池请求到各自的Provider服务提供者,像舱壁一样对Provider进行隔离。

    对于不同的服务提供者设置不同的RPC调用线程池,这种模式被称为舱壁模式,如图所示

    使用舱壁可以避免对单个Provider的RPC消耗掉所有资源,从而防止由于某一个服务性能低而引起的级联故障和雪崩效应。

    一般来说,RPC线程与Web容器的IO线程也是需要隔离的。如下图所示

    当Provider A的用户请求涉及Provider B和Provider C的RPC时,Provider A的IO线程会将任务交给对应的RPC线程池里面的RPC线程来执行,Provider A的IO线程就可以去干别的事情去了,当RPC线程执行完远程调用的任务之后,就会将调用的结果返回给IO线程。

    如果RPC线程池耗尽了,IO线程池也不会受到影响,从而实现RPC线程与Web容器的IO线程的相互隔离。

    Hystrix提供了两种RPC隔离方式:线程池隔离和信号量隔离

    2.Hystrix线程池隔离

    Hystrix既可以为HystrixCommand命令默认创建一个线程池,又可以关联上一个指定的线程池。

    每一个线程池都有一个Key,名为Thread Pool Key(线程池名)。

    如果没有为HystrixCommand指定线程池,Hystrix就会为HystrixCommand创建一个与GroupKey(命令组Key)同名的线程池,当然,如果与Group Key同名的线程池已经存在,就直接进行关联。

    也就是说,默认情况下,HystrixCommand命令的Thread Pool Key与GroupKey是相同的。

    总体来说,线程池是Hystrix中RPC调用隔离的关键,所有的监控、调用、缓存等都围绕线程池展开。

    如果要指定线程池,可以在Setter中定制线程池的Key和属性

    默认情况下,在Spring Cloud中,Hystrix会为每一个Command Group Key自动创建一个同名的线程池。

    而在Hystrix客户端,每一个RPC目标Provider的Command Group Key默认值为它的应用名称(Application Name)

    如果某个应用(如uaa-provider)需要发起对demo-provider的远程调用,那么Hystrix为该Provider创建的RPC线程池的名称默认为demo-provider,专门用于对demo-provider的REST服务进行RPC调用和隔离

    3.Hystrix线程池隔离配置

    在Spring Cloud服务提供者中,如果需要使用Hystrix线程池进行RPC隔离,就可以在应用的配置文件中进行相应的配置。

    下面是demo-provider的RPC线程池配置的实例

    hystrix:
      threadpool:
        default:
          coreSize: 10 #线程池核心线程数
          maximumSize: 20 #线程池最大线程数
          allowMaximumSizeToDivergeFromCoreSize: true #线程池maximumSize最大线程数是否生效
          keepAliveTimeMinutes:10 #设置可空闲时间,单位为分钟
       command:
         default: #全局默认配置
           execution: #RPC隔离的相关配置
             isolation:
               strategy: THREAD #配置请求隔离的方式,这里为线程池方式
               thread:
               timeoutInMilliseconds: 100000 #RPC执行的超时时间,默认为1000毫秒
               interruptOnTimeout: true #发生超时后是否中断方法的执行,默认值为true

    对上面的实例中用到的与Hystrix线程池有关的配置项介绍如下:

    1.hystrix.threadpool.default.coreSize:设置线程池的核心线程数。

    2.hystrix.threadpool.default.maximumSize:设置线程池的最大线程数

    起作用的前提是allowMaximumSizeToDivergeFromCoreSize的属性值为true。
    maximumSize属性值可以等于或者大于coreSize值,当线程池的线程不够用时,Hystrix会创建新的线程,直到线程数达到maximumSize的值,创建的线程为非核心线程。

    3.hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize:该属性允许maximumSize起作用。

    4.hystrix.threadpool.default.keepAliveTimeMinutes:该属性设置非核心线程的存活时间。

    如果某个非核心线程的空闲超过keepAliveTimeMinutes设置的时间,非核心线程就会被释放。

    其单位为分钟,默认值为1,默认情况下,表示非核心线程空闲1分钟后释放。

    5.hystrix.command.default.execution.isolation.strategy:该属性设置RPC远程调用HystrixCommand命令的隔离策略。

    它有两个可选值:THREAD和SEMAPHORE,默认值为THREAD。

    THREAD表示使用线程池进行RPC隔离,SEMAPHORE表示通过信号量来进行RPC隔离和限制并发量。

    6.hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:设置调用者等待HystrixCommand命令执行的超时限制。

    超过此时间,HystrixCommand被标记为TIMEOUT,并执行回退逻辑。

    超时会作用在HystrixCommand.queue(),即使调用者没有调用get()去获得Future对象。

     

    以上配置是application应用级别的默认线程池配置,覆盖的范围为系统中的所有RPC线程池。

    另一种配置方式

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
     
    import static com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager.*;
     
    /*
     * 注意: @HystrixCommand 注解方式依赖 AOP, 不支持在同一个类的内部方法之间直接调用, 必须将被调用类作为 bean 注入并调用
     */
    public class DemoCircuitBreakerAnnotation {
     
        /**
         * 使用 THREAD 模式及线程池参数、通用参数说明
         */
        @HystrixCommand(
                groupKey = "GroupAnnotation",
                commandKey = "HystrixAnnotationThread",
                fallbackMethod = "HystrixAnnotationThreadFallback",
                /*
                 * 线程池名, 具有同一线程池名的方法将在同一个线程池中执行
                 *
                 * 默认值: 方法的groupKey
                 */
                threadPoolKey = "GroupAnnotationxThreadPool",
                threadPoolProperties = {
                    /*
                     * 线程池Core线程数及最大线程数
                     *
                     * 默认值: 10
                     */
                    @HystrixProperty(name = CORE_SIZE, value = "10"),
                    /*
                     * 线程池线程 KeepAliveTime 单位: 分钟
                     *
                     * 默认值: 1
                     */
                    @HystrixProperty(name = KEEP_ALIVE_TIME_MINUTES, value = "1"),
                    /*
                     * 线程池最大队列长度
                     *
                     * 默认值: -1, 此时使用 SynchronousQueue
                     */
                    @HystrixProperty(name = MAX_QUEUE_SIZE, value = "100"),
                    /*
                     * 达到这个队列长度后, 线程池开始拒绝后续任务
                     *
                     * 默认值: 5, MaxQueueSize > 0 时有效
                     */
                    @HystrixProperty(name = QUEUE_SIZE_REJECTION_THRESHOLD, value = "90"),
                },
                commandProperties = {
                    /*
                     * 以 THREAD (线程池)模式执行, run 方法将被一个线程池中的线程执行
                     *
                     * 注意: 由于有额外的线程调度开销, THREAD 模式的性能不如 NONE 和 SEMAPHORE 模式, 但隔离性比较好
                     *
                     * 默认值: THREAD
                     */
                    @HystrixProperty(name = EXECUTION_ISOLATION_STRATEGY, value = "THREAD"),
                    /*
                     * 方法执行超时后是否中断执行线程
                     *
                     * 默认值: true, THREAD 模式下有效
                     */
                    @HystrixProperty(name = EXECUTION_ISOLATION_THREAD_INTERRUPT_ON_TIMEOUT, value = "true"),
                    /*
                     * 超时时间参数
                     * 在 THREAD 模式下, 方法超时后 Hystrix 默认会中断原方法的执行线程, 并标记这次方法的执行结果为失败(影响方法的健康值)
                     * 同时另开一个线程执行 fallback, 最终返回 fallback 的结果
                     *
                     * 默认值: 1000
                     */
                    @HystrixProperty(name = EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "500")
                    /*
                     * 其余参数参考上面的例子, 或者使用默认值
                     */
                })
        public String HystrixAnnotationThread(String param) {
            return "Run with " + param;
        }
        public String HystrixAnnotationThreadFallback(String param, Throwable ex) {
            return String.format("Fallback with param: %s, exception: %s", param, ex);
        }
    }
     

    4.Hystrix信号量隔离

    除了使用线程池进行资源隔离之外,Hystrix还可以使用信号量机制完成资源隔离。

    信号量所起到的作用就像一个开关,而信号量的值就是每个命令的并发执行数量,当并发数高于信号量的值时就不再执行命令。

    比如,如果Provider A的RPC信号量大小为10,那么它同时只允许有10个RPC线程来访问服务Provider A,其他的请求都会被拒绝,从而达到资源隔离和限流保护的作用。

    Hystrix信号量机制不提供专用的线程池,也不提供额外的线程,在获取到信号量之后,执行HystrixCommand命令逻辑的线程还是之前Web容器的IO线程。

    实际RPC远程调用最终是由Web容器的IO线程来完成,这样就带来了一个问题

    由于RPC远程调用是一种耗时的操作,如果IO线程被长时间占用,就会导致Web容器请求处理能力下降,

    甚至会在一段时间内因为IO线程被占满而造成Web容器无法对新的用户请求及时响应,最终导致Web容器崩溃。

    所以,信号量隔离机制不适用于RPC隔离。 

    执行过程

    信号量可以细分为run执行信号量和fallback回退信号量

    IO线程在执行HystrixCommand命令之前需要抢到run执行信号量,成功之后才允许执行HystrixCommand.run()方法。

    如果争抢失败,就准备回退,

    但是在执行HystrixCommand.getFallback()回退方法之前,还需要争抢fallback回退信号量,成功之后才允许执行HystrixCommand.getFallback()回退方法。

    如果都获取失败,操作就会直接终止。

    5.Hystrix信号量隔离的配置

    涉及Hystrix命令属性配置器HystrixCommandProperties.Setter()的实例方法如下:

    1.withExecutionIsolationSemaphoreMaxConcurrentRequests(int)

    此方法设置执行信号量的大小,也就是HystrixCommand.run()方法允许的最大请求数。

    如果达到最大请求数,后续的请求就会被拒绝。

    在Web容器中,抢占信号量的线程应该是容器(比如Tomcat)IO线程池中的一小部分,所以信号量的数量不能大于容器线程池的大小,否则就起不到保护作用。

    执行信号量的大小默认值为10

    2.withFallbackIsolationSemaphoreMaxConcurrentRequests(int)

    此方法设置回退信号量的大小,也就是HystrixCommand.getFallback()方法允许的最大请求数。

    如果达到最大请求数,后续的回退请求就会被拒绝。

    另一种配置方式

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
     
    import static com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager.*;
     
    /*
     * 注意: @HystrixCommand 注解方式依赖 AOP, 不支持在同一个类的内部方法之间直接调用, 必须将被调用类作为 bean 注入并调用
     */
    public class DemoCircuitBreakerAnnotation {
     
        /**
         * 使用 SEMAPHORE 模式及通用参数说明
         */
        @HystrixCommand(
                groupKey = "GroupAnnotation",
                commandKey = "HystrixAnnotationSemaphore",
                fallbackMethod = "HystrixAnnotationSemaphoreFallback",
                commandProperties = {
                    /*
                     * 以 SEMAPHORE (信号量)模式执行, 原方法将在调用此方法的线程中执行
                     *
                     * 如果原方法无需信号量限制, 可以选择使用 NONE 模式
                     * NONE 模式相比 SEMAPHORE 模式少了信号量获取和判断的步骤, 效率相对较高, 其余执行流程与 SEMAPHORE 模式相同
                     *
                     * 默认值: THREAD
                     */
                    @HystrixProperty(name = EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),
                    /*
                     * 执行 run 方法的信号量上限, 即由于方法执行未完成停留在 run 方法内的线程最大个数
                     * 执行线程退出 run 方法后释放信号量, 其他线程获取不到信号量无法执行 run 方法
                     *
                     * 默认值: 1000, SEMAPHORE 模式下有效
                     */
                    @HystrixProperty(name = EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "100"),
                    /*
                     * 执行 fallback 方法的信号量上限
                     *
                     * 注意: 所有模式(NONE|SEMAPHORE|THREAD) fallback 的执行都受这个参数影响
                     *
                     * 默认值: Integer.MAX_VALUE
                     */
                    @HystrixProperty(name = FALLBACK_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "1000"),
                    /*
                     * 超时时间参数
                     * 在 SEMAPHORE 模式下, 方法超时后 Hystrix 不会中断原方法的执行线程, 只标记这次方法的执行结果为失败(影响方法的健康值)
                     * 同时另开一个线程执行 fallback, 最终返回 fallback 的结果
                     *
                     * 默认值: 1000
                     */
                    @HystrixProperty(name = EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "500"),
                    /*
                     * 方法各项指标值存活的滑动时间窗口长度, 每经过一个时间窗口长度重置各项指标值, 比如: 方法的健康值
                     *
                     * 默认值: 10000
                     */
                    @HystrixProperty(name = METRICS_ROLLING_STATS_TIME_IN_MILLISECONDS, value = "10000"),
                    /*
                     * 滑动时间窗口指标采样的时间分片数, 分片数越高时, 指标汇总更新的频率越高, 指标值的实时度越好, 但同时也占用较多 CPU
                     * 采样过程: 将一个滑动时间窗口时长根据分片数等分成多个时间分片, 每经过一个时间分片将最新一个时间分片的内积累的统计数据汇总更新到时间窗口内存活的已有指标值中
                     *
                     * 注意: 这个值只影响 Hystrix Monitor 上方法指标值的展示刷新频率,不影响熔断状态的判断
                     *
                     * 默认值: 10
                     */
                    @HystrixProperty(name = METRICS_ROLLING_STATS_NUM_BUCKETS, value = "10"),
                    /*
                     * 健康值采样的间隔, 相当于时间片长度, 每经过一个间隔将这个时间片内积累的统计数据汇总更新到时间窗口内存活的已有健康值中
                     *
                     * 健康值主要包括: 方法在滑动时间窗口内的总执行次数、成功执行次数、失败执行次数
                     *
                     * 默认值: 500
                     */
                    @HystrixProperty(name = METRICS_HEALTH_SNAPSHOT_INTERVAL_IN_MILLISECONDS, value = "500"),
                    /*
                     * 一个滑动时间窗口内, 方法的执行次数达到这个数量后方法的健康值才会影响方法的熔断状态
                     *
                     * 默认值: 20
                     */
                    @HystrixProperty(name = CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10"),
                    /*
                     * 一个采样滑动时间窗口内, 方法的执行失败次数达到这个百分比且达到上面的执行次数要求后, 方法进入熔断状态, 后续请求将执行 fallback 流程
                     *
                     * 默认值: 50
                     */
                    @HystrixProperty(name = CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "50"),
                    /*
                     * 熔断状态停留时间, 方法进入熔断状态后需要等待这个时间后才会再次尝试执行原方法重新评估健康值. 再次尝试执行原方法时若请求成功则重置健康值
                     *
                     * 默认值: 5000
                     */
                    @HystrixProperty(name = CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "5000")
                })
        public String HystrixAnnotationSemaphore(String param) {
            return "Run with " + param;
        }
        public String HystrixAnnotationSemaphoreFallback(String param, Throwable ex) {
            return String.format("Fallback with param: %s, exception: %s", param, ex);
        }
    }

    6.信号量隔离与线程池隔离的区别

    六、RPC保护之熔断器模式

    熔断器的工作机制

    统计最近RPC调用发生错误的次数,然后根据统计值中的失败比例等信息决定是否允许后面的RPC调用继续,或者快速地失败回退。

    熔断器的3种状态

    1.closed:熔断器关闭状态

    这也是熔断器的初始状态,此状态下RPC调用正常放行。

    2.open:失败比例到一定的阈值之后,熔断器进入开启状态

    此状态下RPC将会快速失败,执行失败回退逻辑。

    3.half-open:在打开open状态一定时间之后(睡眠窗口结束),熔断器进入半开启状态

    小流量尝试进行RPC调用放行。

    如果尝试成功,熔断器就变为closed状态,RPC调用正常;如果尝试失败,熔断器就变为open状态,RPC调用快速失败。

    熔断器状态之间相互转换的逻辑关系图

    断路器重要配置说明

     HystrixCommandProperties.Setter propertiesSetter =HystrixCommandProperties.Setter()
     //至少有3个请求,熔断器才达到熔断触发的次数阈值
     .withCircuitBreakerRequestVolumeThreshold(3)
     //熔断器中断请求5秒后会进入half-open状态,尝试放行
     .withCircuitBreakerSleepWindowInMilliseconds(5000)
     //错误率超过60%,快速失败
     .withCircuitBreakerErrorThresholdPercentage(60)
     //启用超时
     .withExecutionTimeoutEnabled(true)
     //执行的超时时间,默认为1000毫秒(ms),这里设置为500毫秒
     .withExecutionTimeoutInMilliseconds(500)
     //可统计的滑动窗口内的buckets数量,用于熔断器和指标发布
     .withMetricsRollingStatisticalWindowBuckets(10)
     //可统计的滑动窗口的时间长度
     //这段时间内的执行数据用于熔断器和指标发布
     .withMetricsRollingStatisticalWindowInMilliseconds(10000);

     有以下配置器的命令配置需要重点说明一下:

    1.通过withExecutionTimeoutInMilliseconds(int)方法将默认为1000毫秒的执行超时上限设置为500毫秒

    也就是说,只要HystrixCommand.run()的执行时间超过500毫秒,就会触发Hystrix超时回退

    2.通过withCircuitBreakerRequestVolumeThreshold(int)方法将熔断器触发熔断的最少请求次数的默认值20次改为了3次

    3.通过withCircuitBreakerErrorThresholdPercentage(int)方法设置错误率阈值百分比的值为60

    在滑动窗口时间内,当错误率超过此值时,熔断器进入open状态,所有请求都会触发失败回退(fallback),错误率阈值百分比的默认值为50。

    4. 通过withCircuitBreakerSleepWindowInMilliseconds(5000)

    在命令的熔断器打开后,熔断器默认会有5秒的睡眠等待时间,在这段时间内的所有请求直接执行回退方法;

    5秒之后,熔断器会进入half-open状态,尝试放行一次命令执行,如果成功就关闭熔断器,状态转成closed,否则熔断器回到open状态。


     

    展开全文
  • Hystix常规配置与使用

    2019-08-30 11:36:53
    Hystrix设计目标: 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的 阻止故障的连锁反应 快速失败并迅速恢复 回退并优雅降级 提供近实时的监控与告警 Hystrix遵循的设计原则: ...
  • SpringCloud -- Hystix

    2020-06-30 21:03:04
    Hystix,英文意思是豪猪,全身是刺,看起来就不好惹,是一种保护机制。 Hystrix也是Netflix公司的一款组件。 Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。 微服务...
  • Hystix、Feign、Zuul网关

    2021-11-09 16:42:23
    1 Hystix 1.1 简介 Hystix,即熔断器。 主页:https://github.com/Netflix/Hystrix/ 如图所示: Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。如图所示: 1.2. 熔断...
  • SpringCloud的入门(Hystix、Feign、Zuul) Hystix 简介 Hystix,即熔断器。 主页:https://github.com/Netflix/Hystrix/ Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联...
  • 到此,一个简单基于ribbon的Hystix熔断机制就配置好了 二、基于Feign client的Hystrix 配置 1、复制项目重命名为springcloud-moveServer-hystrix修改调用方 pom.xml 配置文件,追加 Hystrix 配置类: ...
  • 1.线程隔离,服务降级(服务的消费方做降级处理) 当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。 这就好比去买鱼,平常超市买鱼会...
  • 1.微服务中,服务之间的调用关系复杂。一个请求有可能需要多个微服务接口才能实现。如果一次请求出现问题就会直接堵塞,占用一次tomcat链接。如果访问这个出现问题的请求就会造成tomcat请求链接都被占用,最终导致...
  • SpringCloud02-Feign、Hystix 和 Gateway 文章目录 SpringCloud02-Feign、Hystix 和 Gateway 3.Feign 声明式服务调用 3.1 Feign 声明式服务调用 3.2 feign 超时设置 3.3 Feign 日志记录 4.Hystrix 熔断器 4.1 Hystix...
  • SpringCloud笔记04-Hystix

    千次阅读 2020-09-21 13:35:14
    传送门 ...Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。 Hystix依赖: <dependency> <groupId>org.springframework.cloud</groupId>
  • 会配置Hystix熔断 会使用Feign进行远程调用 能独立搭建Zuul网关 能编写Zuul的拦截器 1.Hystix 1.1.简介 Hystix,即熔断器。 主页:https://github.com/Netflix/Hystrix/ [外链图片转存失败(img-kyEpQX6S-...
  • 快速学习-熔断器Hystix

    2019-12-31 17:52:36
    1.Hystix 1.1.简介 Hystix,即熔断器。 主页:https://github.com/Netflix/Hystrix/ Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。 1.2.熔断器的工作机制: 正常...
  • springcloud之Hystix

    2019-01-14 18:03:21
    Hystix简介 Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。 熔断器的工作机制: 正常工作的情况下,客户端请求调用服务API接口: 当有服务出现异常时,直接...
  • SpringCloud微服务治理二(Robbin,Hystix,Feign) SpringCloud微服务治理三(Zuul网关) 6.负载均衡Ribbon 在刚才的案例中,我们启动了一个user-service,然后通过DiscoveryClient来获取服务实例信息,然后获取ip和...
  • 搭建SpringCloud项目五(Hystix)并使用自定义配置
  • 统一的调用接口 统一的权限校验 集成了ribbon 集成了hystrix 具体部署的时候网关前面部署nginx或者f5负载均衡器部署在最前端,客户直接访问
  • 认识微服务-Hystix

    2019-06-11 14:59:10
    认识微服务-Hystix1.Hystix1.1.简介1.2.熔断器的工作机制:1.3.动手实践1.3.1.引入依赖1.3.2.开启熔断1.3.2.改造消费者1.3.3.改造服务提供者1.3.4.启动测试1.3.5.优化 1.Hystix 1.1.简介 Hystix,即熔断器。 主页:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,506
精华内容 602
关键字:

hystix