【2.1】Java微服务:详解Hystrix

news2024/10/6 10:33:12

 ✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。
🍎个人主页:Meteors.的博客
💞当前专栏: 深度学习
✨特色专栏: 知识分享
🥭本文内容:【2.1】Java微服务:详解Hystrix
📚 ** ps **  : 阅读这篇文章如果有问题或者疑惑,欢迎各位在评论区提问或指出!

 -----------------------------------------------------       目录       ---------------------------------------------------------

目录

 一、基本介绍

1. 基本介绍

2. 实现原理

二、相关功能

1. 请求缓存

概述

缺点

Redis的方式

1) 导入依赖

2) 添加配置文件

3) 增加Redis 配置

4)增加缓存注解

5) 接口实现类增加缓存注解

6)结果

2. 请求合并实现

1). pom文件添加依赖

2). 在实现类进行请求合并

3)开启熔断注解

4)模拟同时发起多个请求

3.线程池隔离

1)介绍

2)优点

3)缺点

4)代码示例

4. 信号量隔离

1)介绍

2)代码示例

3) 线程池颗粒与信号隔离对比

5.服务熔断

1)介绍

2)调用

 其他

 参考文献:


---------------------------------------------------------------------------------------------------------------------------------

 一、基本介绍

1. 基本介绍

Hystix是一个延迟和容错库,旨在隔离对远程系统、服务和第三方库的访问点,停止级联故障,并在不可避免发生故障的复杂分布式系统中实现快速恢复。主要靠Spring的AOP实现


2. 实现原理

  • 正常情况下,断路器关闭,服务消费者正常请求微服务
  • 一段时间内,失败率达到一定阈值,断路器将断开,此时不在请求服务提供者,而只是快速失败的方法(断路方法)
  • 断路器打开一段时间,自动进入“半开”状态,此时,断路器可允许一个请求方法服务提供者,如果请求调用成功,则关闭断路器,否则将保持断路器打开状态

断路器hystrix是保证了局部发生的错误,不会错扩展到整个系统, 从而保证系统 的即便出现局部问题也不会造成系统雪崩

二、相关功能

1. 请求缓存

概述

Hystirx为了降低访问服务的评率,支持将一个q8ingqiu与返回接口做缓存处理。如果再次请求的URL没有变化,nameHystrix不会请求服务,而是直接从请求中将结果放回。这样可以大大降低访问服务的压力。

缺点

  • 本地缓存,集群模式下缓存无法同步
  • 不支持第三方缓存容器,如Redis、MemCache

(现在一般都是使用Redis集成方案)

Redis的方式

1) 导入依赖

        <!--  spring boot data redis 依赖  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--  commons-pool2 对象池依赖 1  -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

2) 添加配置文件

  # redis缓存
  redis:
    timeout: 10000 #设置连接超时时间
    host: 127.0.0.1
    port: 6379
    database: 0
    lettuce:
      pool:
        max-active: 8 # 最大连接数,默认8
        max-wait: 10000 # 最大连接阻塞时间,单位毫秒,默认-1
        max-idle: 200 #最大空闲连接,默认8
        min-idle: 5 #最小空闲连接默认 0

3) 增加Redis 配置

package cn.itmeteors.order.config;

/**
 * Redis 配置类
 */

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

@Configuration
public class RedisConfig {

    // 重写 RedisTemplate 序列化
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 为 String 类型 key 设置序列化器
        template.setKeySerializer(new StringRedisSerializer());
        // 为 String 类型 value 设置序列化器
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        // 为 Hash 类型 key 设置序列化器
        template.setHashKeySerializer(new StringRedisSerializer());
        // 为 Hash 类型 value 设置序列化器
        template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    // 重写 Cache 序列化
    @Bean
    public RedisCacheManager redisCacheManager(RedisTemplate redisTemplate) {
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisTemplate.getConnectionFactory());
        RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
                // 设置默认过期时间 30 min
                .entryTtl(Duration.ofMinutes(30))
                // 设置 key 和 value 的序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getKeySerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(redisTemplate.getValueSerializer()));
        return new RedisCacheManager (redisCacheWriter, redisCacheConfiguration);
    }

}

4)增加缓存注解

5) 接口实现类增加缓存注解

    @Cacheable(cacheNames = "orderService:order:select")
    public Order selectOrderById(Long orderId) {    // 调用list
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用RestTemplate发起http请求,查询用户
        // 2.1.url路径
        String url = "http://userservice/user/list";
        // 2.2.发送http请求,实现远程调用
        List<User> userList = restTemplate.getForObject(url, List.class);
        assert userList != null;
        order.setUser(userList);
        return order;
    }

6)结果

2. 请求合并实现

1). pom文件添加依赖

        <!-- spring-cloud netflix hystrix 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

2). 在实现类进行请求合并

 3)开启熔断注解

@EnableCaching
// 开启熔断器注解 2 选 1,@EnableHystrix 封装了 @EnableCircuitBreaker
// @EnableHystrix
@EnableCircuitBreaker
@EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class)
public class OrderApplication {

4)模拟同时发起多个请求

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.利用RestTemplate发起http请求,查询用户
        // 2.1.url路径
        String url = "http://userservice/user/1";
        String url2 = "http://userservice/user/2";
        String url3 = "http://userservice/user/3";
        String url4 = "http://userservice/user/4";
        String url5 = "http://userservice/user/5";
        // 2.2.发送http请求,实现远程调用
        Future<User> user = (Future<User>) restTemplate.getForObject(url, User.class);
        Future<User> user2 = (Future<User>) restTemplate.getForObject(url2, User.class);
        Future<User> user3 = (Future<User>) restTemplate.getForObject(url3, User.class);
        Future<User> user4 = (Future<User>) restTemplate.getForObject(url4, User.class);
        Future<User> user5 = (Future<User>) restTemplate.getForObject(url5, User.class);
        // 3.封装user到Order
        List<User> userList = new ArrayList<>(1);
        try {
            userList.add(user.get());
            userList.add(user2.get());
            userList.add(user3.get());
            userList.add(user4.get());
            userList.add(user5.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        order.setUser(userList);
        // 4.返回
        return order;
    }

3.线程池隔离

1)介绍

对调用的接口进行隔离,一个接口因为并发过高瘫痪时,掉用的另一个接口不会瘫痪

2)优点

  • 使用线程池隔离可以安全「隔离依赖的服务」,减少所依赖服务发生故障时的影响面。比如 A 服务发生异常,导致请求大量超时,对应的线程池被打满,这时并不影响 C、D 服务的调用。

  • 当失败的服务再次变得可用时,线程池将清理并立即恢复,而不需要一个长时间的恢复。

  • 独立的线程池「提高了并发性」

3)缺点

  • 请求在线程池中执行,肯定会带来任务调度、排队和上下文切换带来的 CPU 开销。

  • 因为涉及到跨线程,那么就存在 ThreadLocal 数据的传递问题,比如在主线程初始化的 ThreadLocal 变量,在线程池线程中无法获取。

4)代码示例

   // 声明需要服务容错的方法
    // 线程池隔离
    @HystrixCommand(groupKey = "order-userService-listPool",// 服务名称,相同名称使用同一个线程池
            commandKey = "getList",// 接口名称,默认为方法名
            threadPoolKey = "order-userService-listPool",// 线程池名称,相同名称使用同一个线程池
            commandProperties = {
                    // 超时时间,默认 1000ms
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
                            value = "5000")
            },
            threadPoolProperties = {
                    // 线程池大小
                    @HystrixProperty(name = "coreSize", value = "6"),
                    // 队列等待阈值(最大队列长度,默认 -1)
                    @HystrixProperty(name = "maxQueueSize", value = "100"),
                    // 线程存活时间,默认 1min
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    // 超出队列等待阈值执行拒绝策略
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "100")
            }, fallbackMethod = "selectUserListFallback")
    public List<User> getList() {
        return userMapper.getAll();
    }

    // 托底数据
    private List<User> selectUserListFallback() {
        System.out.println("-----获得托底数据-----");
        return Arrays.asList(
                new User(1L, "A", "地点1"),
                new User(2L, "B", "地点2"),
                new User(3L, "C", "地点3")
        );
    }

4. 信号量隔离

1)介绍

每次调用线程,当前请求通过计数信号量进行限制,当信号量大于了最大请求数 maxConcurrentRequests 时,进行限制,调用 fallback 接口快速返回。信号量的调用是同步的,也就是说,每次调用都得阻塞调用方的线程,直到结果返回。这样就导致了无法对访问做超时(只能依靠调用协议超时,无法主动释放)

2)代码示例

// 声明需要服务容错的方法
    // 信号量隔离
    @HystrixCommand(commandProperties = {
            // 超时时间,默认 1000ms
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
                    value = "5000"),
            // 信号量隔离
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY,
                    value = "SEMAPHORE"),
            // 信号量最大并发,调小一些方便模拟高并发
            @HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS,
                    value = "6")
    }, fallbackMethod = "selectUserListFallback")
    public List<User> getList() {
        return userMapper.getAll();
    }

    // 托底数据
    private List<User> selectUserListFallback() {
        System.out.println("-----获得托底数据-----");
        return Arrays.asList(
                new User(1L, "A", "地点1"),
                new User(2L, "B", "地点2"),
                new User(3L, "C", "地点3")
        );
    }

3) 线程池颗粒与信号隔离对比

隔离方式是否支持超时是否支持熔断隔离原理是否是异步调用资源消耗
线程池隔离支持支持每个服务单独用线程池支持同步或异步
信号量隔离不支持支持通过信号量的计数器同步调用,不支持异步

5.服务熔断

1)介绍

服务熔断是一种机制,用于在出现服务故障、超时或异常情况时,阻止请求继续发送到故障的服务上。当达到一定的失败阈值时,熔断器会打开,后续的请求将被快速失败,而不再去调用故障的服务。当故障情况得到修复后,熔断器会尝试关闭,恢复对服务的正常调用。

2)调用

在上面的代码执行fallbackMethod就会执行服务熔断

 其他

除了上述功能,Hystrix还有实时监控、指标收集、恢复等功能,这里会留到后面的时候进行更新,大家如果现在要学习的话,可以从官网或其它地方得到相关的介绍和代码

 参考文献:

GitHub - Netflix/Hystrix: Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable. - GitHub - Netflix/Hystrix: Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.https://github.com/Netflix/Hystrix

 最后,

后续文章会陆续更新,希望文章对你有所帮助..!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/841770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

每天五分钟机器学习:梯度下降算法和正规方程的比较

本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…

Vue-组件二次封装

本次对el-input进行简单封装进行演示 封装很简单&#xff0c;就给激活样式的边框(主要是功能) 本次封装主要使用到vue自带的几个对象 $attrs&#xff1a;获取绑定在组件上的所有属性$listeners: 获取绑定在组件上的所有函数方法$slots&#xff1a; 获取应用在组件内的所有插槽 …

MATLAB的设置路径

在主页下的 或者在命令行输入path&#xff0c;命令行会出现所有路径 必须要将某些函数.m文件以及一些类文件包含在路径当中&#xff0c;否则在脚本代码中输入代码时&#xff0c;不会有代码提示

【Azure】office365邮箱测试的邮箱账号因频繁连接邮箱服务器而被限制连接 引起邮箱显示异常

azure微软office365邮箱会对频繁连接自身邮箱服务器的IP地址进行&#xff0c;连接邮箱服务器IP限制&#xff0c;也就是黑名单&#xff0c;释放时间不确定&#xff0c;但至少一天及以上。 解决办法&#xff0c;换一个IP&#xff0c;或者新注册一个office365邮箱再重试。 以下是…

Mysql5.7 、MySQL 8.0 加密、解密函数

PASSWORD 8.0版本取消了&#xff0c;只能在5.7中使用 返回字符串str的加密版本&#xff0c;41位长的字符串&#xff0c;加密结果不可逆 格式 select PASSWORD(xxx) from DUAL;MD5 5.7和8.0 都支持 返回字符串str的MD5加密后的值&#xff0c;若参数为null&#xff0c;则…

不同风格Tabs

风格 通过type设置风格&#xff0c;支持三种风格card、borderCard、line 核心代码 组件双向绑定 modelVal: {type: Number | String,required: true}, model: {prop: modelVal,event: change} this.$emit(change, this.active) 代码 <template><div:class"[…

【链表OJ 1】移除链表元素val

大家好&#xff0c;欢迎来到我的博客&#xff0c;此题是关于链表oj的第一题&#xff0c;此后还会陆续更新博客&#xff0c;如有错误&#xff0c;欢迎大家指正。 来源:https://leetcode.cn/problems/remove-linked-list-elements/description/ 题目: 方法一:定义prev和cur指针…

基于STM32微控制器的物联网(IoT)节点设计与实现

基于STM32微控制器的物联网(IoT)节点的设计和实现。我们讨论物联网节点的基本概念和功能,并详细介绍了STM32微控制器的特点和优势。然后,我们将探讨如何使用STM32开发环境和相关的硬件模块来设计和实现一个完整的物联网节点。最后,我们将提供一个示例代码,展示如何在STM3…

侯捷 C++面向对象编程笔记——9 复合 委托

9 复合 委托 9.1 Composition 复合 类似于c中结构里有结构——class里有class deque 是一个已经存在的功能很多的类&#xff08;两头进出的队列&#xff09;&#xff1b;利用deque的功能来实现queue的多种操作 该例只是复合的一种情况——设计模式 Adapter 9.1.1 复合下的构造…

【JavaEE进阶】Spring创建与使用

文章目录 一. 创建 Spring 项目1.1 创建一个Maven项目1.2 添加Spring依赖1.4. 创建一个启动类 二. 将 Bean 对象存放至 Spring 容器中三. 从 Spring 容器中读取到 Bean1. 得到Spring对象2. 通过Spring 对象getBean方法获取到 Bean对象【DI操作】 一. 创建 Spring 项目 接下来使…

实时服务器监控

为 IT 基础架构建立适当的监控系统的重要性不容低估&#xff0c;管理员使用的监控解决方案可确保通过消除瓶颈和优化资源使用以获得最佳性能来充分发挥基础架构的潜力。 多年来&#xff0c;IT 基础架构变得越来越复杂&#xff0c;对网络监控的需求也随之增加&#xff0c;虽然网…

R语言3_安装SeurateData

环境Ubuntu22/20, R4.1 在命令行中键入&#xff0c; apt-get update apt install libcurl4-openssl-dev libssl-dev libxml2-dev libcairo2-dev libgtk-3-dev # libcairo2-dev :: systemfonts # libgtk :: textshaping进入r语言交互环境&#xff0c;键入&#xff0c; instal…

运动蓝牙耳机哪个最好、最好用的运动蓝牙耳机推荐

在奔跑的律动中&#xff0c;一款优秀的运动耳机能为我们带来动力。今天&#xff0c;我为大家推荐五款经过精心挑选的运动耳机&#xff0c;它们不仅具备卓越的音质和稳定的连接性&#xff0c;还采用舒适的佩戴设计和耐用的防水功能&#xff0c;可以让我们在运动中畅享音乐的同时…

数据结构之栈和队列---c++

栈和队列的简单介绍 栈 栈是一个“先进后出”结构 队列 入队演示 队列是一种“先进先出”的结构 出队演示 接下来我们开始本次的内容 栈实现队列 分析 1.我们可以老老实实的写一个栈然后将所有的接口函数实现出来&#xff0c;最后再进行实现队列&#xff0c;但是显然…

git开发过程中的使用

1、先创建本地分支&#xff0c;然后修改代码 2、本地提交 push 3、合并为主分支 回到master分支

【【萌新的STM32 学习-6】】

萌新的STM32 学习-6 BSP 文件夹&#xff0c;用于存放正点原子提供的板级支持包驱动代码&#xff0c;如&#xff1a;LED、蜂鸣器、按键等。 本章我们暂时用不到该文件夹&#xff0c;不过可以先建好备用。 CMSIS 文件夹&#xff0c;用于存放 CMSIS 底层代码&#xff08;ARM 和 ST…

Linux——设备树

目录 一、Linux 设备树的由来 二、Linux设备树的目的 1.平台识别 2.实时配置 3.设备植入 三、Linux 设备树的使用 1.基本数据格式 2.设备树实例解析 四、使用设备树的LED 驱动 五、习题 一、Linux 设备树的由来 在 Linux 内核源码的ARM 体系结构引入设备树之前&#x…

Vue——webpack

webpack 一、Install1.全局安装2.局部安装 二、总结1.打包2.定义脚本3.配置文件定义&#xff08;webpack.config.js)4.项目重新加载依赖5.webpack打包Css6.style-loader 一、Install 1.全局安装 npm install webpack webpack-cli -g2.局部安装 以项目为单位&#xff0c;一个项…

2023中国数字人力峰会|用「消失的Ta」解读数字化人效管理

7月28日&#xff0c;DHR公会主办的「2023中国数字人力峰会」在北京顺利举办。盖雅工场联合创始人兼CEO章新波带来主题为「消失的它」的精彩分享。以下为分享内容&#xff1a; 近期&#xff0c;大家都在讨论消失的Ta&#xff0c;我也想借此话题举几个例子&#xff0c;聊聊对于企…

thinkphp8.0多应用模式下提示控制器不存在

thinkphp 8.0 开启多应用模式 1、按照官方文档说明 &#xff0c;已经安装了 think-multi-app composer require topthink/think-multi-app 2、控制器的命名空间也没写错。 3、访问路径与目录名、控制器、方法名一样&#xff0c;访问地址是没错的。 4、网上有说&#xff0c;在…