Hystrix服务降级隔离

我的基本理解:

限流:限制当前ip访问量

降级:削弱部分服务特性

隔离:为每一个服务绑定合理的线程池

使用Hystrix实现服务隔离

Hystrix 是一个微服务关于服务保护的框架,是Netflix开源的一款针对分布式系统的延迟和容错解决框架,目的是用来隔离分布式服务故障。它提供线程和信号量隔离,以减少不同服务之间资源竞争带来的相互影响;提供优雅降级机制;提供熔断机制使得服务可以快速失败,而不是一直阻塞等待服务响应,并能从中快速恢复。Hystrix通过这些机制来阻止级联失败并保证系统弹性、可用。

什么是服务隔离

当大多数人在使用Tomcat时,多个HTTP服务会共享一个线程池,假设其中一个HTTP服务访问的数据库响应非常慢,这将造成服务响应时间延迟增加,大多数线程阻塞等待数据响应返回,导致整个Tomcat线程池都被该服务占用,甚至拖垮整个Tomcat。因此,如果我们能把不同HTTP服务隔离到不同的线程池,则某个HTTP服务的线程池满了也不会对其他服务造成灾难性故障。这就需要线程隔离或者信号量隔离来实现了。

使用线程隔离或信号隔离的目的是为不同的服务分配一定的资源,当自己的资源用完,直接返回失败而不是占用别人的资源。

Hystrix实现服务隔离两种方案

Hystrix的资源隔离策略有两种,分别为:线程池和信号量。

线程池方式

1、 使用线程池隔离可以完全隔离第三方应用,请求线程可以快速放回。 2、 请求线程可以继续接受新的请求,如果出现问题线程池隔离是独立的不会影响其他应用。 
3、 当失败的应用再次变得可用时,线程池将清理并可立即恢复,而不需要一个长时间的恢复。 
4、 独立的线程池提高了并发性

缺点: 
线程池隔离的主要缺点是它们增加计算开销(CPU)。每个命令的执行涉及到排队、调度和上 下文切换都是在一个单独的线程上运行的。

依赖包

<parent>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-parent</artifactId>

            <version>2.0.0.RELEASE</version>

      </parent>

      <dependencies>

            <dependency>

                  <groupId>org.springframework.boot</groupId>

                  <artifactId>spring-boot-starter-web</artifactId>

            </dependency>

            <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->

            <dependency>

                  <groupId>org.apache.httpcomponents</groupId>

                  <artifactId>httpclient</artifactId>

            </dependency>

            <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->

            <dependency>

                  <groupId>com.alibaba</groupId>

                  <artifactId>fastjson</artifactId>

                  <version>1.2.47</version>

            </dependency>

            <dependency>

                  <groupId>com.netflix.hystrix</groupId>

                  <artifactId>hystrix-metrics-event-stream</artifactId>

                  <version>1.5.12</version>

            </dependency>

            <dependency>

                  <groupId>com.netflix.hystrix</groupId>

                  <artifactId>hystrix-javanica</artifactId>

                  <version>1.5.12</version>

            </dependency>

      </dependencies>

测试

public class OrderHystrixCommand extends HystrixCommand<JSONObject> {

      @Autowired

      private MemberService memberService;

public OrderHystrixCommand(MemberService memberService) {

            super(setter());

            this.memberService = memberService;

      }

 

      protected JSONObject run() throws Exception {

            JSONObject member = memberService.getMember();

            System.out.println("当前线程名称:" + Thread.currentThread().getName() + ",订单服务调用会员服务:member:" + member);

            return member;

      }

 

      private static Setter setter() {

 

            // 服务分组

            HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("members");

            // 服务标识

            HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey("member");

            // 线程池名称

            HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey("member-pool");

            // #####################################################

            // 线程池配置 线程池大小为10,线程存活时间15 队列等待的阈值为100,超过100执行拒绝策略

            HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter().withCoreSize(10)

                        .withKeepAliveTimeMinutes(15).withQueueSizeRejectionThreshold(100);

            // ########################################################

            // 命令属性配置Hystrix 开启超时

            HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()

                        // 采用线程池方式实现服务隔离

                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)

                        // 禁止

                        .withExecutionTimeoutEnabled(false);

            return HystrixCommand.Setter.withGroupKey(groupKey).andCommandKey(commandKey).andThreadPoolKey(threadPoolKey)

                  .andThreadPoolPropertiesDefaults(threadPoolProperties).andCommandPropertiesDefaults(commandProperties);

 

      }

 

      @Override

      protected JSONObject getFallback() {

            // 如果Hystrix发生熔断,当前服务不可用,直接执行Fallback方法

System.out.println("系统错误!");

            JSONObject jsonObject = new JSONObject();

            jsonObject.put("code", 500);

            jsonObject.put("msg", "系统错误!");

            return jsonObject;

      }

}

信号量

使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,当请求进来时先判断计数 器的数值,若超过设置的最大线程个数则拒绝该请求,若不超过则通行,这时候计数器+1,请求返 回成功后计数器-1。

与线程池隔离最大不同在于执行依赖代码的线程依然是请求线程 
tips:信号量的大小可以动态调整, 线程池大小不可以

public class OrderHystrixCommand2 extends HystrixCommand<JSONObject> {

      @Autowired

      private MemberService memberService;

 

      /**

       * @param group

       */

      public OrderHystrixCommand2(MemberService memberService) {

            super(setter());

            this.memberService = memberService;

      }

 

      protected JSONObject run() throws Exception {

 

            // Thread.sleep(500);

            // System.out.println("orderIndex线程名称" +

            // Thread.currentThread().getName());

            // System.out.println("success");

            JSONObject member = memberService.getMember();

            System.out.println("当前线程名称:" + Thread.currentThread().getName() + ",订单服务调用会员服务:member:" + member);

            return member;

      }

 

      private static Setter setter() {

            // 服务分组

            HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("members");

            // 命令属性配置 采用信号量模式

            HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()

                      .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)

                        // 使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,当请求进来时先判断计数

                        // 器的数值,若超过设置的最大线程个数则拒绝该请求,若不超过则通行,这时候计数器+1,请求返 回成功后计数器-1

                        .withExecutionIsolationSemaphoreMaxConcurrentRequests(50);

            return HystrixCommand.Setter.withGroupKey(groupKey).andCommandPropertiesDefaults(commandProperties);

      }

 

      @Override

      protected JSONObject getFallback() {

            // 如果Hystrix发生熔断,当前服务不可用,直接执行Fallback方法

            System.out.println("系统错误!");

            JSONObject jsonObject = new JSONObject();

            jsonObject.put("code", 500);

            jsonObject.put("msg", "系统错误!");

            return jsonObject;

      }

}

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_39276448/article/details/85265001