4、Hystrix使用和源码分析

Hystrix使用和源码分析

1丶Hystrix介绍
  • 微服务架构中存在的问题

    由于调用链中的某个服务出现问题,引起整个系统的雪崩

  • Hystrix是什么

    Hystrix是用于处理延迟和容错的开源库

  • Hystrix的作用是怎么

    • 服务隔离丶服务熔断丶服务降级(快速失败)
    • 限流
    • 请求合并和请求响应
    • 自带单体和集群监控
2丶Hystrix架构图

image-20230611133002655

3丶Hystrix环境搭建

(1)引入依赖image-20230611134002455

4丶HystrixCommand四种使用方式
  • 实现类image-20230611143416388

  • 各个使用方式区别image-20230611183118056

  1. execute()方式(同步执行)

    image-20230611143623721

  2. queue()方式(异步执行)image-20230611144216329

  3. obServer()方式

    • 阻塞式调用image-20230611144732804
    • 非阻塞式调用image-20230611144931604
  4. toObserver

    • 阻塞调用image-20230611145738315
    • 非阻塞调用image-20230611145943215
5丶HystrixObserver Command 演示
  • 实现类image-20230611184732461image-20230611184638848
  1. observer()方式image-20230611185302399
  2. toObserver()方式image-20230611185536997
  3. 总结image-20230611190147108
6丶Hystrix配置之GroupKey和CommandKey
  1. GroupKey:

    • Hystrix中GroupKey是唯一必填项
    • GroupKey可以作为分组监控和报警作用
    • GroupKey将作为线程池的默认名称
  2. CommandKey:

    • Hystrix可以不填写CommandKey
    • 默认Hystrix会通过反射类名命名CommandKey
    • 在Setting中加入AndCommandKey进行命名

    image-20230612181125003

7丶Hystrix请求缓存
  • Hystrix支持将请求结果进行本地缓存

  • 通过实现GetCacheKey方法来判断是否取出缓存

  • 请求缓存要求必须在同一个上下文

  • 可以用RequestCacheEnable开启请求缓存

    (1) 测试方法

    image-20230612183105516

    (2) 重写获得缓存Key方法

    image-20230612183440932

    (3) 缓存开关(默认打开)image-20230612183620981

  • 总结image-20230612183753767

8丶Hystrix请求合并
  • Hystrix支持将多个请求合并成一次请求
  • Hystrix请求合并要求两次请求必须足够“近”
  • 请求合并分为局部合并和全局合并两种
  • 通过Collapser可以设置相关参数
  1. 8.2、请求合并对象的构建

    /**
    
     * 泛型参数: 批量返回类型,批量处理中每次处理中响应类型,批量处理中每次请求参数类型
       */
       public class CommandCollapser extends HystrixCollapser<List<String>,String ,Integer> {
       private Integer id;
    public CommandCollapser(Integer id){
        super(Setter.withCollapserKey(HystrixCollapserKey.Factory.asKey("CommandCollapser")));
        this.id =id;
    }
    
    /**
     * 获取请求参数
     * @return
     */
    @Override
    public Integer getRequestArgument() {
        return id;
    }
    
    /**
     * 批量业务处理
     * @param collection
     * @return
     */
    @Override
    protected HystrixCommand<List<String>> createCommand(Collection<CollapsedRequest<String, Integer>> collection) {
        return new BatchCommand(collection);
    }
    
    /**
     * 批量处理结果与请求业务之间映射关系处理
     * @param strings
     * @param collection
     */
    @Override
    protected void mapResponseToRequests(List<String> strings, Collection<CollapsedRequest<String, Integer>> collection) {
        int count = 0;
        Iterator<CollapsedRequest<String, Integer>> iterator = collection.iterator();
        while(iterator.hasNext()){
            CollapsedRequest<String, Integer> request = iterator.next();
            String result = strings.get(count++);
            request.setResponse(result);
        }
    }
    
    class BatchCommand extends HystrixCommand<List<String>>{
        private Collection<CollapsedRequest<String, Integer>> collection;
        public BatchCommand(Collection<CollapsedRequest<String, Integer>> collection){
            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("BatchCommand")));
            this.collection = collection;
        }
        @Override
        protected List<String> run() throws Exception {
            System.err.println("currentThread: " + Thread.currentThread().getName());
            List<String> result = Lists.newArrayList();
            Iterator<CollapsedRequest<String, Integer>> iterator = collection.iterator();
            while (iterator.hasNext()){
                CollapsedRequest<String, Integer> request = iterator.next();
                Integer reqParam = request.getArgument();
                // 具体业务请求
                result.add("msb request:" + reqParam);
            }
            return result;
        }
    }
    }
    
  2. 总结image-20230612190655765

9丶Hystrix隔离术
  1. Hystrix隔离命名ThreadPoolkey

    • Hystrix可以不填写ThreadPoolKey
    • 默认Hystrix会使用GroupKey命名线程池
    • 在Setting中加入andThreadPoolKey进行命名
  2. Hystrix隔离介绍

    • Hystrix提供了信号量和线程两种隔离手段
    • 线程隔离会在单独的线程中执行业务逻辑
    • 信号量隔离在调用线程上执行
    • 官方推荐优先线程隔离
  3. Hystrix隔离演示image-20230612191338298

    • 我们直接执行CommandTest中的execute

    image-20230612192451596

    • 打印出线程名称 My thread ,这说明1、我们的指定是生效的 2、我们现在用的是线程池中的线程
      My thread-1 也就是线程池里面的第一个线程

      image-20230612192511003

    • 更改线程模式

      image-20230612192528608

    • 再运行,看结果线程是main 主线程

      image-20230612192638106

      1. 线程池和信号量的区别

        线程隔离

        • 应用自身完全受保护,不会受其他依赖影响
        • 有效降低接入新服务的风险
        • 依赖服务出现问题,应用自身可以快速反应问题
        • 可以通过实时刷新动态属性减少依赖问题影响

        信号量隔离

        • 信号量隔离是轻量级的隔离术
        • 无网络开销的情况推荐使用信号量隔离
      2. Hystrix线程隔离和信号量隔离参数解析及演示

        (1)线程隔离参数演示

        线程池相关配置:

        image-20230612192926418image-20230612192943441

        (2) 信号量演示

        ​ 信号量隔离配置:image-20230612194010012

        ​ 设置为信号量模式image-20230612194043232

        ​ 创建线程

        class MyThread extends Thread{
        	private String name;
        	public MyThread(String name){
            	this.name = name;
        	}
        
        	@Override
        	public void run() {
            	CommandDemo commandDemo = new CommandDemo(name);
            	System.out.println("commandDemo result="+commandDemo.execute());
        	}
        }
        

        ​ 参数设置image-20230612194323562

        ​ 执行就会报错如下报信号量不足的问题image-20230612194346656

10丶Hystrix快速失败与降级
  1. 降级介绍

    • 降级就是当服务无法返回正常结果的时候,返回一个默认的值
    • Command降级需要实现fallback方法
    • ObservableCommand降级实现resumeWithFallback方法
  2. 重写降级内容image-20230612194551399

    • 运行image-20230612194616258

    • 总结image-20230612194649752

    • 降级触发原则

      • 熔断器处于开启状态
      • 线程池或信号量已满
      • HystrixBadRequestException以外的异常
      • 运行超时

      看一下图image-20230612194837914

    • 快速失败

      • Hystrix提供了快速失败的机制 【Hystrix提供了快速失败的机制 ,这个机制就是依赖我们的
        fallback,当出现任何异常都会触发fallback,fallback就会把失败的业务逻辑返回给前端】
      • 当不实现fallback方法时会将异常直接抛出
11丶Hystrix熔断器介绍和使用
  1. Hystrix熔断器介绍

    • 熔断器是一种开关,用来控制流量是否执行业务逻辑
    • 熔断器核心指标:快照时间窗
    • 熔断器核心指标:请求总数阈值
    • 熔断器核心指标:错误百分比阈值

    熔断器的开启有两种方式,1、通过指标来判断是否开启 2、手动开启关闭 ,一般我们都是基于指标
    来开启,不会手动开启关闭

    我们看一下这个图,熔断器的底层算法——滑动窗口image-20230612200620703

  2. 熔断器状态

    • 熔断器开启:所有请求都会进入fallback方法
    • 熔断器半开启:间歇性让请求触发run方法
    • 熔断器关闭:正常处理业务请求
    • 默认情况下熔断器开启5秒后进入半开启状态

    图的演示:

    image-20230612201031412

    image-20230612205349919

  3. Hystrix熔断器演示
    熔断机制相关配置image-20230612201136706

    更改对应测试代码

    @Test
    public void CBTest() throws InterruptedException {
        // 正确 - 业务
        CommandDemo c1 = new CommandDemo("msb-demo");
        System.out.println(c1.execute());
    
        // 错误 - 业务
        CommandDemo c2 = new CommandDemo("error-demo");
        System.out.println(c2.execute());
    
    // 正确 - 业务
    CommandDemo c3 = new CommandDemo("msb-demo");
    System.out.println(c3.execute());
    

    }

    更改业务代码,让其报错误异常![image-20230612201912287](https://img-blog.csdnimg.cn/55665a11be934570aefd055be2a7b174.png)
    
    + 测试强制开启参数![image-20230612201953871](https://img-blog.csdnimg.cn/272f63d4d4dc492cac47e8c94896e3d4.png)
    
    + 开启后全部降级![image-20230612202021474](https://img-blog.csdnimg.cn/f7c867b80afd435ea34c05ef7d97e69d.png)
    
    + 半开状态(更改参数)![image-20230612202057739](https://img-blog.csdnimg.cn/c7da79374dfa478d9fcf07e5b397ba5a.png)
    
      因为默认情况下熔断器开启5秒后进入半开启状态,所以我们需要先修面5秒后才能进入半开启
      状态
    
      进入半开启状态 如果第一次调用失败,则熔断器再次进入开启状态, 如果第一次调用成功,则
      熔断器处于关闭状态
    
      ![image-20230612202145397](https://img-blog.csdnimg.cn/21d1aea8925d414d986929184c6f95bf.png)
    
12丶Hystrix环境集成丶整合Feign以及线程大小设置
  1. Hystrix环境集成
  • 引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    </dependencies>
    
  • 开启Hystriximage-20230612205923335

  • 增加HystrixCommand注解

    @HystrixCommand(fallbackMethod = "fallbackMethod",
                commandProperties = {
                        @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
                        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value= "200"),
                        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
                        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "50")
                },
                threadPoolProperties = {
                        @HystrixProperty(name = "coreSize", value = "1"),
                        @HystrixProperty(name = "maxQueueSize", value = "10"),
                        @HystrixProperty(name = "keepAliveTimeMinutes", value = "1000"),
                        @HystrixProperty(name = "queueSizeRejectionThreshold", value = "8"),
                        @HystrixProperty(name = "metrics.rollingStats.numBuckets", value = "12"),
                        @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1500")
                })
    
    public String fallbackMethod(String userId){
    
        return "服务降级返回默认用户信息 userId:" + userId;
    }
    
  • 数据测试

    由于我们超时时间是200ms,我们让他休眠1s,这样都出现超时,就会出现降级

    image-20230612210232244image-20230612210240945

  1. Hystrix整合Feign
  • 开启Feign

    feign:
    hystrix:
    enabled: true

  • 降级内容实现

    @Service
    public class UserFeignClientFallBack  implements UserFeignClient {
        @Override
        public String getUser(String userId) {
            return "获取用户失败进行降级:" + userId;
        }
    }
    
  • 降级配置image-20230612214533322

  • 根据具体错误信息进行降级

    • 降级FallBackFactory

      @Component
      public class UserFeignClientFallBackFactory implements FallbackFactory<UserFeignClient> {
          @Override
          public UserFeignClient create(Throwable cause) {
              return new UserFeignClient() {
                  @Override
                  public String getUser(String userId) {
                      String message = cause.getMessage();
                      return "根据不同的异常进行不同到的处理方式";
                  }
              };
          }
      }
      
    • 进行配置image-20230612214734142

3丶实战技巧:如何设置线程池

首先呢,我们一定要明白一个概念,就是在我们业务系统中呢,有一个很重要的衡量指标叫QPS,
当然我们一般说QPS的其实是一个统称,更精确地说他其image-20230612214825866

4丶总结

image-20230612214858260

13丶源码分析

image-20230612214930407

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hystrix是Netflix开源的一款容错框架,用于处理分布式系统中的故障和延迟。它主要用于防止服务雪崩效应,并提供了故障转移和服务降级的机制。 Hystrix的原理是通过隔离和限制对依赖服务的访问来提高系统的弹性。它通过使用线程池来隔离不同的服务调用,并设置超时时间来限制请求的执行时间。当某个依赖服务出现故障或延迟时,Hystrix会自动触发服务降级,返回一个备选的响应结果,避免故障扩散到整个系统。 使用Hystrix需要以下几个步骤: 1. 添加Hystrix依赖:在项目的构建文件中添加Hystrix的依赖,例如在Maven项目中添加以下依赖: ```xml <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.5.18</version> </dependency> ``` 2. 定义Hystrix命令:创建一个继承自HystrixCommand的类,重写run()方法,在其中实现对依赖服务的调用逻辑。 ```java public class MyCommand extends HystrixCommand<String> { protected MyCommand() { super(HystrixCommandGroupKey.Factory.asKey("MyGroup")); } @Override protected String run() throws Exception { // 调用依赖服务的逻辑 return "Hello, World!"; } } ``` 3. 执行Hystrix命令:在需要调用依赖服务的地方,创建并执行Hystrix命令。 ```java String result = new MyCommand().execute(); ``` 4. 设置服务降级:在HystrixCommand中重写getFallback()方法,定义当依赖服务出现故障时的备选响应结果。 ```java @Override protected String getFallback() { return "Fallback response"; } ``` 通过以上步骤,你可以使用Hystrix来保护你的分布式系统免受故障和延迟的影响,并实现服务的降级和故障转移。当然,这只是Hystrix的基本使用教程,你还可以进一步了解Hystrix的更多高级特性和配置选项来满足你的具体需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值