SpringCloud(四):Hystrix熔断器介绍【Greenwich 版】

2023-10-21 11:40

本文主要是介绍SpringCloud(四):Hystrix熔断器介绍【Greenwich 版】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述
Hystrix的中文含义是 “豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与 Hystrix 本身的功能不谋而合,因此 Netflix 团队将该框架命名为 Hystrix,并使用了对应的卡通形象做作为 logo。

分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况,这种现象被称为服务雪崩效应。为了应对服务雪崩,一种常见的做法是手动服务降级。而 Hystrix 的出现,给我们提供了另一种选择。

服务雪崩效应的定义

服务雪崩效应是一种因 服务提供者 的不可用导致 服务调用者 的不可用,并将不可用 逐渐放大 的过程。如果所示:
在这里插入图片描述
上图中,A 为服务提供者,B 为 A 的服务调用者,C 和 D 是 B 的服务调用者。当 A 的不可用,引起 B 的不可用,并将不可用逐渐放大 C 和 D 时,服务雪崩就形成了。

服务雪崩形成的原因

我把服务雪崩的参与者简化为 服务提供者 和 服务调用者,并将服务雪崩产生的过程分为以下三个阶段来分析形成的原因:

  1. 服务提供者不可用
  2. 重试加大流量
  3. 服务调用者不可用

在这里插入图片描述
服务雪崩的每个阶段都可能由不同的原因造成,比如造成 服务不可用 的原因有:

  • 硬件故障
  • 程序 Bug
  • 缓存击穿
  • 用户大量请求

硬件故障可能为硬件损坏造成的服务器主机宕机,网络硬件故障造成的服务提供者的不可访问。
缓存击穿一般发生在缓存应用重启,所有缓存被清空时,以及短时间内大量缓存失效时。大量的缓存不命中,使请求直击后端,造成服务提供者超负荷运行,引起服务不可用。
在秒杀和大促开始前,如果准备不充分,用户发起大量请求也会造成服务提供者的不可用。

而形成 重试加大流量 的原因有:

  • 用户重试
  • 代码逻辑重试

在服务提供者不可用后,用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单。
服务调用端的会存在大量服务异常后的重试逻辑。这些重试都会进一步加大请求流量。
最后,服务调用者不可用 产生的主要原因是:

  • 同步等待造成的资源耗尽

当服务调用者使用 同步调用 时,会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态,于是服务雪崩效应产生了。

服务雪崩的应对策略

针对造成服务雪崩的不同原因,可以使用不同的应对策略:

  • 流量控制
  • 改进缓存模式
  • 服务自动扩容
  • 服务调用者降级服务

流量控制 的具体措施包括:

  • 网关限流
  • 用户交互限流
  • 关闭重试

因为Nginx的高性能, 目前一线互联网公司大量采用Nginx+Lua的网关进行流量控制, 由此而来的OpenResty也越来越热门.

用户交互限流的具体措施有: 1. 采用加载动画,提高用户的忍耐等待时间. 2. 提交按钮添加强制等待时间机制.

改进缓存模式 的措施包括:

  • 缓存预加载
  • 同步改为异步刷新

服务自动扩容 的措施主要有:

  • AWS的auto scaling

服务调用者降级服务 的措施包括:

  • 资源隔离
  • 对依赖服务进行分类
  • 不可用服务的调用快速失败

资源隔离主要是对调用服务的线程池进行隔离.

我们根据具体业务,将依赖服务分为: 强依赖和弱依赖. 强依赖服务不可用会导致当前业务中止,而弱依赖服务的不可用不会导致当前业务的中止.

不可用服务的调用快速失败一般通过 超时机制, 熔断器 和熔断后的 降级方法 来实现.

使用Hystrix预防服务雪崩

Hystrix的设计原则包括:

  • 资源隔离
  • 熔断器
  • 命令模式

资源隔离
货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个, 如下图所示:
在这里插入图片描述
这种资源隔离减少风险的方式被称为:Bulkheads(舱壁隔离模式).
Hystrix将同样的模式运用到了服务调用者上,Hystrix的隔绝策略分为两种:线程隔离信号量隔离

线程隔离:Hystrix在用户请求和服务之间加入了线程池。Hystrix为每个依赖调用分配一个小的线程池。用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满调用将被立即拒绝,进行降级处理,用户的请求不会被阻塞,至少可以看到一个执行结果(例如返回友好的提示信息),而不是无休止的等待或者看到系统崩溃。
信号量隔离:每次调用线程,当前请求通过计数信号量进行限制,当信号大于了最大请求数时,进行限制,调用fallback接口快速返回。

官网对信号量隔离的描述建议
Generally the only time you should use semaphore isolation for HystrixCommands is when the call is so high volume (hundreds per second, per instance) that the overhead of separate threads is too high; this typically only applies to non-network calls.
理解下两点:

  • 隔离的细粒度太高,数百个实例需要隔离,此时用线程池做隔离开销过大
  • 通常这种都是非网络调用的情况下

一般来说,只有当调用负载非常高时(例如每个实例每秒调用数百次)才需要使用信号量隔离,因为这种场景下使用线程隔离开销会比较高。信号量隔离一般仅适用于非网络调用的隔离。Hystrix中默认并且推荐使用线程隔离。

二者的比较

隔离策略线程隔离信号量隔离
线程HystrixCommand将会在单独的线程上执行HystrixCommand将会在调用线程上执行
开销排队、调度、上下文开销等无线程切换,开销低
异步支持不支持
并发支持支持(最大线程池大小)支持(最大信号量上限)
是否支持超时支持,直接返回不支持,如果阻塞,只能通过调用协议(如:socket超时才能返回)
是否支持熔断支持,当线程池到达maxSize后,再请求会触发fallback接口进行熔断支持,当信号量达到maxConcurrentRequests后。再请求会触发fallback

熔断器模式
熔断器模式定义了熔断器开关相互转换的逻辑:
在这里插入图片描述
服务的健康状况 = 请求失败数 / 请求总数.
熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.

当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态,当熔断器开关打开时, 请求被禁止通过.

当熔断器开关处于打开状态, 经过一段时间后(默认5s), 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过.

熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.

命令模式
Hystrix有两个请求命令 HystrixCommandHystrixObservableCommand
其中HystrixCommand依赖调用方法是run,服务降级方法是getFallback
HystrixObservableCommand依赖调用方法是construct,服务降级方法是resumeWithFallback

HystrixCommand是发出一个请求,返回一个结果

  • execute() — 从依赖的服务返回一个单一的结果对象,同步阻塞式;
  • queue() — 返回一个Future对象,异步非阻塞式;

HystrixObservableCommand可以发出多个请求,返回一个结果

  • observe() — 返回Obervable对象,热执行
  • toObservable() — 返回Obervable对象,冷执行

热执行就是不管你事件有没有注册完(onCompleted(),onError,onNext这三个事件注册),就去执行我的业务方法即(HystrixObservableCommand实现类中的construct()方法)
冷执行就是,事件监听方法注册完成后,才执行业务方法

Hystrix的内部处理逻辑

在这里插入图片描述

  1. 构建Hystrix的Command对象, 调用执行方法.
  2. Hystrix检查当前服务的熔断器开关是否开启, 若开启, 则执行降级服务getFallback方法.
  3. 若熔断器开关关闭, 则Hystrix检查当前服务的线程池是否能接收新的请求, 若超过线程池已满, 则执行降级服务getFallback方法.
  4. 若线程池接受请求, 则Hystrix开始执行服务调用具体逻辑run方法.
  5. 若服务执行失败, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.
  6. 若服务执行超时, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.
  7. 若服务执行成功, 返回正常结果.
  8. 若服务降级方法getFallback执行成功, 则返回降级结果.
  9. 若服务降级方法getFallback执行失败, 则抛出异常.

参考

防雪崩利器:熔断器 Hystrix 的原理与使用

相关阅读

项目代码
SpringCloud 汇总【Greenwich 版】
SpringCloud(一):Eureka注册中心【Greenwich 版】
SpringCloud(二):Ribbon负载均衡【Greenwich 版】
SpringCloud(三):Feign声明式服务调用【Greenwich 版】
SpringCloud(四):Hystrix熔断器介绍【Greenwich 版】
SpringCloud(五):Hystrix的请求熔断与服务降级【Greenwich 版】
SpringCloud(六):Hystrix的请求合并【Greenwich 版】
SpringCloud(七):Hystrix仪表盘与Turbine集群监控【Greenwich 版】
SpringCloud(八):Zuul网关【Greenwich 版】
SpringCloud(九):Config配置中心【Greenwich 版】
SpringCloud(十):Bus消息总线【Greenwich 版】
SpringCloud(十一):Stream消息驱动 + RabbitMQ【Greenwich 版】
SpringCloud(十二):Sleuth链路跟踪【Greenwich 版】

这篇关于SpringCloud(四):Hystrix熔断器介绍【Greenwich 版】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/254161

相关文章

springboot集成easypoi导出word换行处理过程

《springboot集成easypoi导出word换行处理过程》SpringBoot集成Easypoi导出Word时,换行符n失效显示为空格,解决方法包括生成段落或替换模板中n为回车,同时需确... 目录项目场景问题描述解决方案第一种:生成段落的方式第二种:替换模板的情况,换行符替换成回车总结项目场景s

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏