【2.1】Java微服务:详解Hystrix

 ✅作者简介:大家好,我是 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.1port: 6379database: 0lettuce:pool:max-active: 8 # 最大连接数,默认8max-wait: 10000 # 最大连接阻塞时间,单位毫秒,默认-1max-idle: 200 #最大空闲连接,默认8min-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 序列化@Beanpublic 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 序列化@Beanpublic 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到OrderList<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.rhkb.cn/news/78997.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【测试】软件测试工具JMeter简单用法

简明扼要&#xff0c;点到为止。 1. JMeter介绍 JMeter的全称是Apache JMeter&#xff0c;是一款用于软件测试的工具软件&#xff0c;其是开源免费的&#xff0c;由Apache基金会运营。 官网&#xff1a;Apache JMeter - Apache JMeter™ 2. 下载安装及运行 2.1 安装 Java8…

AlmaLinux 9 安装 Go 1.20

AlmaLinux 9 安装 Golang 1.20 1. 下载 go 安装包2. 安装 go3. 配置环境变量4. 确认 go 版本 1. 下载 go 安装包 访问 https://go.dev/dl/&#xff0c;下载你想安装的版本&#xff0c;比如 go1.20.7.linux-amd64.tar.gz&#xff0c; 2. 安装 go (可选)删除旧版本&#xff0c;…

cocos creator 的input.on 不生效

序&#xff1a; 1、执行input.on的时候发现不生效 2、一直按控制台也打印不出来console.log 3、先收藏这篇&#xff0c;因为到时候cocos要开发serveApi的时候&#xff0c;你得选一款趁手的后端开发并且&#xff0c;对习惯用ts写脚本的你来说&#xff0c;node是入门最快&#xf…

Eclipse如何自动添加作者、日期等注释

一、创建类时自动添加注释 1、Window->Preferences 2、Java->Code Syle->Code Templates->Code->New Java files->Edit->要添加的注释->Apply 二、选中要添加的类或者方法通过AltShiftJ快捷键添加 1、Window->Preferences 2、Java->Code Syle…

【Axure教程】移动端二级滑动选择器

今天教大家制作移动端二级滑动选择器的原型模板&#xff0c;该原型已全国一二级省市选择器为案例&#xff0c;因为该原型用中继器做的&#xff0c;所以制作完成之后使用也很方便&#xff0c;只需修改中继器表格里的内容即可 一、效果展示 1. 拖动选择 2. 快捷选择 【原型预览…

ES6 - 对象新增的一些常用方法

文章目录 1&#xff0c;Object.is()2&#xff0c;Object.asign()3&#xff0c;Object.getOwnPropertyDescriptors()4&#xff0c;Object.setPrototypeOf()和getPrototypeOf()5&#xff0c;Object.keys()、values() 和 entries()6&#xff0c;Object.fromEntries()7&#xff0c;…

利用appium抓取app中的信息

一、appium简介 二、appium环境安装 三、联调测试环境 四、利用appium自动控制移动设备并提取数据

nginx+flask+uwsgi部署遇到的坑

文章目录 1.环境&#xff1a;2.uwsgi_conf.ini具体配置内容3.nginx 具体配置4.具体命令(注意使用pip3命令安装)5.服务异常排查 1.环境&#xff1a; centos8 uWSGI 2.0.22 gmssl 3.2.2 nginx version: nginx/1.18.0 项目目录&#xff1a; 2.uwsgi_conf.ini具体配置内容 [uws…

从俩个不确定长度的字符串中找出最长连续公共子串【动态规划】

从俩个不确定长度的字符串中找出最长连续公共子串【动态规划】 输入和输出动态规划 输入和输出 输入&#xff1a; asdfwww cvcasdfeew输出&#xff1a; asdf 动态规划 俩种情况 第一种情况 当比较到i3,j3时&#xff1b;上面最长的公共子字符串长度为f,长度为1&#xff1b; …

AI抠图使用指南:Stable Diffusion WebUI Rembg实用技巧

抠图是图像处理工具的一项必备能力&#xff0c;可以用在重绘、重组、更换背景等场景。最近我一直在探索 Stable Diffusion WebUI 的各项能力&#xff0c;那么 SD WebUI 的抠图能力表现如何呢&#xff1f;这篇文章就给大家分享一下。 安装插件 作为一个生成式AI&#xff0c;SD…

Mr. Cappuccino的第56杯咖啡——Mybatis拦截器

Mybatis拦截器 概述应用场景项目结构实现分页查询其它拦截器的使用 概述 Mybatis允许使用者在映射语句执行过程中的某一些指定的节点进行拦截调用&#xff0c;通过织入拦截器&#xff0c;在不同节点修改一些执行过程中的关键属性&#xff0c;从而影响SQL的生成、执行和返回结果…

项目也能“收纳”?UniPro帮助客户智能管理项目数据

用户是技术产品最终的使用者&#xff0c;他们对产品的需求和期望直接影响着产品的成功与否。通过用户的反馈&#xff0c;开发团队可以深入了解用户的实际需求&#xff0c;将技术的发展方向和优先级与用户需求紧密结合&#xff0c;从而更好地满足市场需求。 UniPro作为国内主流…

wpf 项目中使用 Prism + MaterialDesign

1.通过nuget安装MaterialDesign 2.通过nuget安装Prism 3.修改App.xmal <prism:PrismApplication x:Class"VisionMeasureGlue.App"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/…

应急响应-linux挖矿病毒的实战处置

0x01 服务器现状分析 客户描述服务器卡顿&#xff0c;切通过搜索引擎进去该官网跳转非法页面&#xff0c;但本地访问无异常 0x02 信息收集 通过进程占用情况cpu功率拉满&#xff0c;确定被植入挖矿病毒文件 qq 且存在计划任务update.sh&#xff1a;crontab -l 将该文件上传沙…

C语言案例 99乘法口诀-04

难度2复杂度2 题目&#xff1a;打印99乘法口诀 步骤一&#xff1a;定义程序目标 编写一个C程序&#xff0c;打印99乘法口诀。 步骤二&#xff1a;程序设计 整个程序分别为两个部分&#xff0c;第一部分是使用for循环打印的行数&#xff0c;第二部分是使用for循环控制打印的列…

Gitlab CI/CD笔记-第二天-GitOps的流水线常用关键词(1)

一、常用关键词 在Gitlab项目的根目录需要创建一个 .gitlab-ci.yaml的文件。 这个文件就是定义的流水线。Call :"Pipeline as code" 二、这条流水线怎么写&#xff1f; 一、掌握常用的关键词即可。 1.关键词分类 1.全局关键词 Global Keywards 2.任务关键词…

基于YOLOv7开发构建MSTAR雷达影像目标检测系统

MSTAR&#xff08;Moving and Stationary Target Acquisition and Recognition&#xff09;数据集是一个基于合成孔径雷达&#xff08;Synthetic Aperture Radar&#xff0c;SAR&#xff09;图像的目标检测和识别数据集。它是针对目标检测、机器学习和模式识别算法的研究和评估…

On Evaluation of Embodied Navigation Agents 论文阅读

论文信息 题目&#xff1a;On Evaluation of Embodied Navigation Agents 作者&#xff1a;Peter Anderson&#xff0c;Angel Chang 来源&#xff1a;arXiv 时间&#xff1a;2018 Abstract 过去两年&#xff0c;导航方面的创造性工作激增。这种创造性的输出产生了大量有时不…

Typescript - 索引签名

目录 1&#xff0c;什么是索引签名1&#xff0c;js 中使用对象的属性2&#xff0c;ts 中的索引签名3&#xff0c;扩展索引签名定义的类型 2&#xff0c;与 Record 对比3&#xff0c;遇到的问题1&#xff0c;索引 key 的类型问题&#xff0c;keyof2&#xff0c;索引 key 的类型问…

烧结钕铁硼的物理性能

烧结钕铁硼永磁体作为核心功能部件&#xff0c;广泛应用在电机、电声、磁吸和传感器等仪器设备中。磁体在服役过程中&#xff0c;会受到机械力、冷热变化、交变电磁场等环境因素&#xff0c;如果发生环境失效&#xff0c;将会严重影响设备的功用&#xff0c;造成巨大的损失。因…