服务的隔离、降级和熔断

1.服务隔离、降级和熔断的产生背景

tomcat底层都会共享一个线程池(自己创建的例外),当某个方法(服务)访问非常慢造成响应延迟,会造成大多数线程阻塞,导致整个线程池被占用甚至拖垮。
线程名定义:线程池名称+线程ID

2.服务隔离解决思路

2.1 线程池隔离

不同的http服务使用不同的线程池,当自己的资源用完,直接返回失败而不是占用别人的资源
优点:可提高并发性
缺点:增加CPU调度开销
使用场景:第三方应用或接口;并发量大

2.2 信号量隔离

原子计数器方式记录当前运行的线程数,超过则拒绝,不超过则+1,返回则-1
使用场景:内部应用或中间件;并发需求不大

区别:信号量可动态调整,但线程池不可以调整

3.服务降级

当服务不可用(服务正在等待、链接超时、网络延迟、服务器响应慢等),客户端一直等待时,调用fallback方法给客户端返回一个错误提示,不让客户端继续等待。
目的:提高用户体验,防止雪崩效应。

4.服务熔断

熔断和保险丝一样,当访问请求过多的时候,达到一个阈值(自己设置)就直接拒绝访问,可以保护当前服务,让服务不会被挂掉,需要和服务降级一起使用。

<dependencies>
    <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;
   }
   @Override
   protected JSONObject run() throws Exception {
      JSONObject member = memberService.getMember();
      System.out.println("当前线程名称:" + Thread.currentThread().getName() + ",订单服务调用会员服务:member:" + member);
      return member;
   }

   /**
    * 使用线程池方式解决隔离
    * @return
    */
   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);

   }

   /**
    * 服务降级
    * @return
    */
   @Override
   protected JSONObject getFallback() {
      // 如果Hystrix发生熔断,当前服务不可用,直接执行Fallback方法
      System.out.println("系统错误!");
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("code", 500);
      jsonObject.put("msg", "系统错误!");
      return jsonObject;
   }
}

使用:
/**
 * 线程池方式解决
 * @return
 * @throws InterruptedException
 */
@RequestMapping("/orderIndexHystrix")
public Object orderIndexHystrix() throws InterruptedException {
   return new OrderHystrixCommand(memberService).execute();
}
信号量方式 和线程池方式也就setter方法不一致,其他的均一致
/**
 * 使用信号量解决隔离
 * @return
 */
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);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值