熔断降级 请求合并 请求缓存 线程池隔离 信号量隔离 openfeign整合Hystrix

〇、Hystrix的解决策略和预防措施:

熔断降级是解决远程调用已经出现问题的解决方案。

请求合并 请求缓存 线程池隔离 信号量隔离都是预防性措施

使用 Hystrix启动类上需要添加注解开启注解支持:

复制代码
        @EnableHystrix
        @EnableCircuitBreaker

测试Hystrix需要的依赖坐标如下:

java 复制代码
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR12</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version> <!-- 请使用最新的版本号 -->
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>


        <!-- 容灾处理依赖。 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>

    </dependencies>

一、熔断降级

熔断是在远程调用的服务器出现问题后,访问不会再进行远程调用甚至调用方法get()。

降级是访问不会再进行远程调用,而是转而调用getDownGrade()方法返回托底数据。

java 复制代码
//  熔断 熔断熔断熔断熔断熔断熔断熔断     熔断      熔断   熔断
    @HystrixCommand(fallbackMethod = "getDownGrade",commandProperties = {
            @HystrixProperty(name = HystrixPropertiesManager
                    .EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS,
                    value = "5000"), // 统计周期,默认10秒
            @HystrixProperty(name = HystrixPropertiesManager
                    .CIRCUIT_BREAKER_ENABLED,
                    value = "true"), // 是否开启熔断,默认true
            @HystrixProperty(name = HystrixPropertiesManager
                    .CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,
                    value = "2"), // 统计周期内,错误几次,开启熔断, 默认20
            @HystrixProperty(name = HystrixPropertiesManager
                    .CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,
                    value = "50"), // 统计周期内,错误百分比达到多少,开启熔断, 默认50
            @HystrixProperty(name = HystrixPropertiesManager
                    .CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS,
                    value = "3000"), // 开启熔断后,多少毫秒不访问远程服务,默认5000毫秒
            @HystrixProperty(name = HystrixPropertiesManager
                    .CIRCUIT_BREAKER_FORCE_OPEN,
                    value = "false"), // 是否强制开启熔断器, 默认false
            @HystrixProperty(name = HystrixPropertiesManager
                    .CIRCUIT_BREAKER_FORCE_CLOSED,
                    value = "false") // 是否强制关闭熔断器, 默认false
    })
    public String get(){
        String forObject = restTemplate.getForObject("http://application-service/getNoParams", String.class);
        return forObject;
    }
    public String getDownGrade(){
        return "服务器繁忙";
    }


二、请求合并

远程调用的服务器端c2有两个方法。一个是针对单个id的,还有一个是针对多个id的相同操作的合并

多个根据id查询user的请求发送至要进行 远程调用的服务器端c1,这时开启请求处理的多个线程阻塞,并将多个id合并为一个List发送一个请求到c2.然后返回的值放在相应线程的FutureTask中。

java 复制代码
//请求合并 请求合并 请求合并 请求合并请求合并 请求合并请求合并 请求合并请求合并 请求合并请求合并 请求合并请求合并 请求合并
    @HystrixCollapser(batchMethod = "getUserByIds",
            scope = com.netflix.hystrix.HystrixCollapser.Scope.GLOBAL,
            collapserProperties = {
                    @HystrixProperty(name =
                            HystrixPropertiesManager.MAX_REQUESTS_IN_BATCH,
                            value = "2"), // 最多合并多少个请求
                    @HystrixProperty(name =
                            HystrixPropertiesManager.TIMER_DELAY_IN_MILLISECONDS,
                            value = "2000") // 最多等待多少毫秒
            }
    )
    public Future<User> getUserById(Integer id){
        System.out.println("正常请求,无请求合并:id="+id);
        restTemplate.postForObject("http://application-service/getUserById", id, User.class);
        return null;
    }
    @HystrixCommand
    public List<User> getUserByIds(List<Integer>ids) throws JsonProcessingException {
        List<LinkedHashMap> list = restTemplate.postForObject("http://application-service/getUserByIds", ids, List.class);
        System.out.println("执行合并方法");
        List<User> list1 = new ArrayList<>();
        for (LinkedHashMap linkedHashMap : list) {

            ObjectMapper objectMapper = new ObjectMapper();
            String s = objectMapper.writeValueAsString(linkedHashMap);
            User user = objectMapper.readValue(s, User.class);
            list1.add(user);
        }

        return list1;
    }


三、请求缓存

这里使用spring cache技术连接redis数据库,在配置文件中配置redis的地址。

@Cacheable()注解自动将方法的返回值存储redis中。

启动类上添加@EnableCaching 开启相关注解支持

java 复制代码
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
java 复制代码
    //请求缓存 请求缓存       请求缓存请求缓存请求缓存请求缓存
    @Cacheable(cacheNames = "getForObject",key = "#id")
    public String cache(Integer id){
        System.out.println("cache方法执行");
        String forObject = restTemplate.getForObject("http://application-service/getNoParams", String.class);
        return forObject;
    }


四、线程池隔离

和船体底部的小船舱一样,底部破了仍然有隔板挡着。

线程池是事先针对远程调用准备的多个线程。

如果不准备线程池,一个远程调用崩了,导致线程阻塞不能释放最终会导致整个服务崩掉。

java 复制代码
  //线程池隔离   线程切换  线程池隔离   线程切换 线程池隔离   线程切换线程池隔离   线程切换
    @HystrixCommand(groupKey = "TbItem",
            commandKey = "selectItemService",
            threadPoolKey = "pool-name",
            threadPoolProperties = {
                    @HystrixProperty(name = HystrixPropertiesManager.CORE_SIZE,
                            value = "3"), // 线程池容量
                    @HystrixProperty(name = HystrixPropertiesManager.KEEP_ALIVE_TIME_MINUTES,
                            value = "5"), // 线程空闲时,最大存活时间是多少分钟
                    @HystrixProperty(name = HystrixPropertiesManager.MAX_QUEUE_SIZE,
                            value = "5"), // 线程池占满时,最多由多少个请求阻塞等待
                    @HystrixProperty(name = HystrixPropertiesManager
                            .QUEUE_SIZE_REJECTION_THRESHOLD,
                            value = "5") // 当阻塞队列MAX_QUEUE_SIZE占满时,可以由多少个
                    // 请求同时阻塞等待后续处理。
            }
    )
    public String selectItemService() {
        System.out.println("selectItemService---"+Thread.currentThread().getName());
        String forObject = restTemplate.getForObject("http://application-service/getNoParams", String.class);
        return forObject;
    }


五、信号量隔离

在一定时间内只允许有限个线程远程调用,其他线程降级。

进行远程调用的线程会拿到许可证,线程结束释放许可证。

java 复制代码
//信号量隔离  信号量隔离信号量隔离信号量隔离
    //在一定时间内只允许2个线程远程调用,其他线程降级
     @HystrixCommand(fallbackMethod = "getDownLoad",
            commandProperties = {
            @HystrixProperty(name = HystrixPropertiesManager
                    .EXECUTION_ISOLATION_STRATEGY,
                    value = "SEMAPHORE"), // 隔离方案。默认线程池隔离。 THREAD | SEMAPHORE
            @HystrixProperty(name = HystrixPropertiesManager
                    .EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS,
                    value = "1"), // 最大信号量
            @HystrixProperty(name = HystrixPropertiesManager
                    .EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS, value = "5000") // 超时时间。信号量隔离中无效,线程池隔离中有效。默认1秒
            }
     )
    public String sign(){
        String forObject = restTemplate.getForObject("http://application-service/getNoParams", String.class);
        return forObject;
     }
    public String getDownLoad(){
        return "服务器繁忙";
    }


六、openfeign整合Hystrix

1)openfeign中使用Hystrix很简单,只需要修改配置文件即可,因为内置好了Hystrix的基础功能容灾处理。

可以看到如果需要Hystrix的其他预防措施还是需要引入Hystrix依赖坐标

2)修改配置文件:

java 复制代码
feign:
  hystrix:
    enabled: true
hystrix: # hystrix 容灾配置
  command: # hystrix 命令配置,就是具体的容灾方案
    default: # 默认环境,相当于全局范围,后续的配置,参考HystrixPropertiesManager中的常量配置
      circuitBreaker: # 熔断配置, 常用。 其他配置不常用。
        enabled: true
        requestVolumeThreshold: 2
        sleepWindowInMilliseconds: 2000
        errorThresholdPercentage: 50
相关推荐
冰帝海岸5 分钟前
01-spring security认证笔记
java·笔记·spring
世间万物皆对象31 分钟前
Spring Boot核心概念:日志管理
java·spring boot·单元测试
没书读了1 小时前
ssm框架-spring-spring声明式事务
java·数据库·spring
小二·1 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic2 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王2 小时前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康2 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神2 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
qq_327342733 小时前
Java实现离线身份证号码OCR识别
java·开发语言
Oak Zhang3 小时前
sharding-jdbc自定义分片算法,表对应关系存储在mysql中,缓存到redis或者本地
redis·mysql·缓存