• Hystrix 请求合并、请求隔离、优化


    请求合并

    引入依赖

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
        <version>2.2.7.RELEASEversion>
    dependency>
    
    
    <dependency>
       <groupId>org.projectlombokgroupId>
       <artifactId>lombokartifactId>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    启动类 加注解@EnableHystrix

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.EnableHystrix;
    
    @SpringBootApplication
    @EnableHystrix
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run (DemoApplication.class, args);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    service服务

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    import java.util.concurrent.Future;
    import java.util.stream.Collectors;
    
    @Component
    @Slf4j
    public class TestServcie {
        @HystrixCollapser(batchMethod = "getUserByIdBatch", //合并 请求方法
                scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,//请求 方式
                collapserProperties = {
                        // 间隔多久的请求会进行合并,默认是 10ms (时间限制)
                        @HystrixProperty(name = "timerDelayInMilliseconds", value = "15"),
                        // 批处理之前,批处理中允许的最 大请求数 (数量限制)
                        @HystrixProperty(name = "maxRequestsInBatch", value = "200"),
                        @HystrixProperty(name = "requestCache.enabled", value = "true")
                }
        )
        // 处理请求合并的方法一定 要支持异步!!,返回值必须是 Future
        // 指出 方法的返回值,参数
        public Future<User> getUserById(Long id) {
            log.info ("------selectProductByIdReturnFuture------");
            return null;
        }
    
    
        /**
         * 因为是 合并请求,所以 返回值是 之前返回值的集合,参数 也是之前参数的的集合
         */
        // 声明 请求合并的方法
        @HystrixCommand
        public List<User> getUserByIdBatch(List<Long> ids) {
            log.info ("=====batch start ====");
            // TODO 对这些数据 批量处理!!
            List<User> users = ids.stream ().map (
                    x -> {
                        User user = new User ();
                        user.setId (x);
                        user.setName ("name :" + x);
                        return user;
                    }
    
            ).collect (Collectors.toList ());
            log.info ("=====batch end ,handle {} 条 request====", ids.size ());
            return users;
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    测试

    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.Future;
    
    @RestController
    @Slf4j
    public class RetryController {
    
        @Resource
        private TestServcie testServcie;
    
        @GetMapping("/test")
        public String getUser(long id) throws ExecutionException, InterruptedException {
            Future<User> f = testServcie.getUserById (id);
            System.out.println (f.get ());
            return "success";
        }
    
    }
    
    
    @Data
    class User {
        private long id;
        private String name;
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    结果:

    在这里插入图片描述

    请求隔离

    线程池隔离(大部分情况下)

    之前请求缓存的例子中,并发的请求一个接口时,造成另一个接口耗时也增多,当时我们使用的缓存解决,还可以使用线程池隔离方式解决
    在这里插入图片描述
    而增加了隔离以后,两个接口隔离,即每个隔离粒度都是个线程池,互不干扰,异步方式提高了并发的性能
    在这里插入图片描述
    这种方式线程每次创建销毁切换等等都需要消耗CPU的性能,如果要隔离的实例太多了,成百上千个,也不推荐使用这种情况

    信号量隔离

    同步方式,阻塞我们 请求方的线程有一个信号量的概念,其实就是个计数器,当请求来的时候先拿到信号量,再执行,执行完释放

    当信号量消耗完时其他的线程就阻塞等待或者快速释放
    在这里插入图片描述
    同步方式,不支持超时,无法用于网络。比如 系统内部的逻辑处理时可以使用

    线程池隔离演示

    引入依赖

    
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
        <version>2.2.7.RELEASEversion>
    dependency>
    
    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    启动类 加注解@EnableHystrix

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.EnableHystrix;
    
    @SpringBootApplication
    @EnableHystrix
    public class DemoApplication {
    
        public static void main(String[] args) {
            SpringApplication.run (DemoApplication.class, args);
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    service服务

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    public class TestServcie {
        // 声明需要服务容错的方法
        // 线程池隔离
        @HystrixCommand(
                commandKey = "getProductList",//接口名称,默认方法名
                threadPoolKey = "order-testServcie-Pool",//线程池名称,相同名称使用同一个线程池
                commandProperties = {
                        // 隔离策略
                        @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
                        //超时时间,默认1000ms, 超时 就走fallbackMethod 降级
                        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200")
                },
                threadPoolProperties = {
    
                        // 线程池核心线程大小
                        @HystrixProperty(name = "coreSize", value = "3"),
                        // 队列 等待阈值(最大队列长度,默认-1)
                        @HystrixProperty(name = "maxQueueSize", value = "10"),
                        // 线程存活时间,默认 1min
                        @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                        // 超出队列 等待阈值 执行拒绝策略!!
                        @HystrixProperty(name = "queueSizeRejectionThreshold", value = "10"),
    
                }, fallbackMethod = "fallbackMtd"
        )
        public String getProductList() {
            log.info (Thread.currentThread ().getName () + "---getProductList----");
    
            return "success";
        }
    
        /**
         * 超出队列等待阈值执行方法
         **/
        private String fallbackMtd() {
            log.info (Thread.currentThread ().getName () + "---降级sorry, the request is timeout----");
            return "降级sorry, the request is timeout";
        }
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    测试

    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    @RestController
    @Slf4j
    public class RetryController {
    
        @Resource
        private TestServcie testServcie;
    
        @GetMapping("/test")
        public String getUser() {
            return testServcie.getProductList ();
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    结果:

    在这里插入图片描述

    信号量隔离演示

    其他不变 修改TestServcie

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import com.netflix.hystrix.contrib.javanica.conf.HystrixPropertiesManager;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    public class TestServcie {
        //信号量隔离
        @HystrixCommand(commandProperties = {
                //超时时间,默认1000ms
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200"),
                //信号量隔离
                @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"),
                //信号量最大并发,调小一点方便模拟高并发
                @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value = "6")
        }, fallbackMethod = "fallbackMtd")
        public String getProductList() {
            log.info (Thread.currentThread ().getName () + "---getProductList----");
    
            return "success";
        }
    
        /**
         * 超出队列等待阈值执行方法
         **/
        private String fallbackMtd() {
            log.info (Thread.currentThread ().getName () + "---降级sorry, the request is timeout----");
            return "降级sorry, the request is timeout";
        }
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    结果:

    在这里插入图片描述

    Hystrix的其他用法

    SpringCloud优化记录

  • 相关阅读:
    武汉新时标文化传媒有限公司抖音小店无货源真的靠谱吗?
    联邦学习模型分类
    java - 包装类
    【微机原理笔记】第 3 章 - 8086/8088的指令系统
    绘制三角波与梯形波
    git cherry-pick命令(合并单个或多个提交记录到当前分支)
    phpstorm+wamp在线调试wordpress
    在VMD上可视化hdf5格式的分子轨迹文件
    CubeMX+BabyOS 使用方法
    《华为项目管理之道》第1章笔记
  • 原文地址:https://blog.csdn.net/qq_30659573/article/details/128005870