【2.1】Java微服务:详解Hystrix

 ✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。
🍎个人主页:Meteors.的博客
💞当前专栏: Java微服务
✨特色专栏: 知识分享
🥭本文内容:【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

 最后,

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

考研408 | 【计算机网络】 数据链路层

导图&#xff1a; 数据链路层概念&#xff1a; 结点&#xff1a;主机、路由器 链路&#xff1a;网络中两个结点之间的物理通道&#xff0c;链路的传输介质主要有双绞线、光纤和微波。分为有线链路、无线链路。 数据链路&#xff1a;网络中两个结点之间的逻辑通道&#xff0…

【Archaius技术专题】「Netflix原生态」动态化配置服务之微服务配置组件变色龙

前提介绍 如果要设计开发一套微服务基础架构&#xff0c;参数化配置是一个非常重要的点&#xff0c;而Netflix也开源了一个叫变色龙Archaius的配置中心客户端&#xff0c;而且Archaius可以说是比其他客户端具备更多生产级特性&#xff0c;也更灵活。*在NetflixOSS微服务技术栈…

uni-app使用vue语法进行开发注意事项

目录 uni-app 项目目录结构 生命周期 路由 路由跳转 页面栈 条件编译 文本渲染 样式渲染 条件渲染 遍历渲染 事件处理 事件修饰符 uni-app 项目目录结构 组件/标签 使用&#xff08;类似&#xff09;小程序 语法/结构 使用vue 具体项目目录如下&#xff1a; 生命…

intelJ IDEA\PHPStorm \WebStorm\PyCharm 通过ssh连接远程Mysql\Postgresql等数据库

最容易出错的地方是在general面板下的host&#xff0c;不应该填真实的host地址&#xff0c;而应该填localhost或者127.0.0.1 具体操作步骤见下图

opencv基础49-图像轮廓02-矩特征cv2.moments()->(形状分析、物体检测、图像识别、匹配)

矩特征&#xff08;Moments Features&#xff09;是用于图像分析和模式识别的一种特征表示方法&#xff0c;用来描述图像的形状、几何特征和统计信息。矩特征可以用于识别图像中的对象、检测形状以及进行图像分类等任务。 矩特征通过计算图像像素的高阶矩来提取特征。这些矩可以…

[OnWork.Tools]系列 05-系统工具

简介 系统工具主要是将Window常用工具的快捷启动的集合 双击快速启动 计算器,记事本,截图,画图工具 控制面板,服务管理,关闭显示器,关机 启动文件夹,我的电脑,管理工具 右键菜单 添加快捷方式到桌面

React diff 根据相对位置的 diff 算法

文章目录 diff 算法没有 key 时的diff通过 key 的 diff查找需要移动的节点移动节点添加新元素移除不存在的元素缺点 diff 算法 没有 key 时的diff 根据新旧列表的长度进行 diff 公共长度相同的部分直接patch新列表长度>旧列表长度则添加&#xff0c;否则删除 function pa…

WPF实战项目十一(API篇):待办事项功能api接口

1、新建ToDoController.cs继承基础控制器BaseApiController&#xff0c;但是一般业务代码不写在控制器内&#xff0c;业务代码写在Service&#xff0c;先新建统一返回值格式ApiResponse.cs&#xff1a; public class ApiResponse{public ApiResponse(bool status, string mess…

git 报错 protocol ‘https‘ is not supported解决

报错原因&#xff1a;选择不了其他分支代码&#xff0c;甚至都看不到其他分支&#xff0c;我这边解决了两次报错&#xff0c;情况如下&#xff1a; 第一种报错&#xff1a; idea中刷新分支报错如下&#xff1a; Fetch Failed protocol https is not supported 话不多说&#…

【安装部署】Mysql下载及其安装的详细步骤

1.下载压缩包 官网地址&#xff1a;www.mysql.com 2.环境配置 1.先解压压缩包 2.配置环境变量 添加环境变量&#xff1a;我的电脑--->属性-->高级-->环境变量-->系统变量-->path 3.在mysql安装目录下新建my.ini文件并&#xff0c;编辑my.ini文件 编辑内容如…

基于TF-IDF+TensorFlow+词云+LDA 新闻自动文摘推荐系统—深度学习算法应用(含ipynb源码)+训练数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境TensorFlow环境方法一方法二 模块实现1. 数据预处理1&#xff09;导入数据2&#xff09;数据清洗3&#xff09;统计词频 2. 词云构建3. 关键词提取4. 语音播报5. LDA主题模型6. 模型构建 系统测试工程源代码下载…

SpringBoot 依赖管理

Spring Boot 依赖管理 在 Spring Boot 中&#xff0c;依赖管理是通过 Maven 或 Gradle 进行管理的。Spring Boot 提供了一种简化的方式来管理和引入依赖项&#xff0c;使得构建和管理项目变得更加容易。下面是一些关于 Spring Boot 依赖管理的基本信息和示例&#xff1a; 使用…

list模拟实现【引入反向迭代器】

文章目录 1.适配器1.1传统意义上的适配器1.2语言里的适配器1.3理解 2.list模拟实现【注意看反向迭代器】2.1 list_frame.h2.2riterator.h2.3list.h2.4 vector.h2.5test.cpp 3.反向迭代器的应用1.使用要求2.迭代器的分类 1.适配器 1.1传统意义上的适配器 1.2语言里的适配器 容…

linux下绑定进程到指定CPU的操作方法

taskset简介 # taskset Usage: taskset [options] [mask | cpu-list] [pid|cmd [args...]] Show or change the CPU affinity of a process. Options: -a, --all-tasks operate on all the tasks (threads) for a given pid -p, --pid operate on ex…

Linux知识点 -- 进程信号(一)

Linux知识点 – 进程信号&#xff08;一&#xff09; 文章目录 Linux知识点 -- 进程信号&#xff08;一&#xff09;一、理解信号1.理解Linux信号2.信号的产生与处理3.常见的信号4.如何理解组合键变成信号5.如何理解信号被进程保存 二、信号的产生1.键盘产生2.核心转储3.系统调…

go-zero 是如何实现计数器限流的?

原文链接&#xff1a; 如何实现计数器限流&#xff1f; 上一篇文章 go-zero 是如何做路由管理的&#xff1f; 介绍了路由管理&#xff0c;这篇文章来说说限流&#xff0c;主要介绍计数器限流算法&#xff0c;具体的代码实现&#xff0c;我们还是来分析微服务框架 go-zero 的源…

LinearAlgebraMIT_7_Ax=0

上节课讲了向量子空间中的列空间和零空间&#xff0c;这节课来讲零空间的(Special solutions)特解&#xff0c;也就是Ax0的特解。在求解特解的核心便是使用消元法求得(row echelon form)阶梯矩阵或者(reduced row echelon form/RREF)最简矩阵。 我们接下来举一个例子&#xff…

【sonar】安装sonarQube免费社区版9.9【Linux】【docker】

文章目录 ⛺sonarQube 镜像容器⛺Linux 安装镜像&#x1f341;出现 Permission denied的异常&#x1f341;安装sonarQube 中文包&#x1f341;重启服务 ⛺代码上传到sonarQube扫描&#x1f341;java语言配置&#x1f341;配置 JS TS Php Go Python⛏️出现异常sonar-scanner.ba…

【设计模式】观察者模式

什么是观察者模式&#xff1f; 观察者模式&#xff08;又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;属于行为型模式的一种&#xff0c;它定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态…

现代C++中的从头开始深度学习:【5/8】卷积

一、说明 在上一个故事中&#xff0c;我们介绍了机器学习的一些最相关的编码方面&#xff0c;例如 functional 规划、矢量化和线性代数规划。 现在&#xff0c;让我们通过使用 2D 卷积实现实际编码深度学习模型来开始我们的道路。让我们开始吧。 二、关于本系列 我们将学习如何…