Spring Cloud - 熔断-程序员宅基地

点击↑上方↑蓝色“编了个程”关注我~

每周至少一篇原创文章

这是本公众号的第 12 篇原创文章

熔断

小齐同学最近正在学Spring Cloud,最近学到熔断这块的知识点,不是很理解,于是请教了公司的大佬老张。

小齐趁空闲时间找到老张:“张哥,我最近在学习Spring Cloud,看到所有书上都说熔断是微服务必须的,可我不用熔断,系统好像也能正常工作。那为什么说它是必须的呢?”

“正常工作是没问题,那发生异常了呢?某个服务挂了或者网络不通的时候会发生什么?”老张反问小齐。

“让我思考一下,如果一个微服务不可用了,那调用它的微服务这个服务就会抛异常,一直到最上层。可这跟熔断又有什么关系?”小齐心中还是有一些疑惑。

老张笑了笑,解释道:“可不只是抛异常怎么简单。在Java中,每一个HTTP请求都会开启一个新线程。而下游服务挂了或者网络不可达,通常线程会阻塞住,直到Timeout。你想想看,如果并发量多一点,这些阻塞的线程就会占用大量的资源,很有可能把自己本身这个微服务所在的机器资源耗尽,导致自己也挂掉。”

小齐有些明白了,追问道:“那是不是最终所有上游微服务都有可能挂掉?”

“是的,这也是称为‘雪崩效应’。最开始是一个微服务挂掉了。随着时间的推移,可能会导致整个系统都不可用。”老张一边回答,一边快速地在电脑上搜出了下面这个图:

雪崩效应

“那熔断具体是怎么解决这个问题的?”小齐点点头,然后继续追问。

老张见小齐似乎有些明悟,但知识点还没有串联起来,便一步一步地引导他:“那你知道Spring Cloud断路器的三种状态吗?”

似乎终于到了小齐自己比较熟悉的知识点,自信地说到:“这个我知道,Spring Cloud一般使用Hystrix来做断路器。就跟电路上的闸差不多。它有三种状态:关闭,开启和半开。最开始是关闭状态的,这个时候所有请求都可以通过;如果错误请求达到一定的阈值,就会变成开启状态,就会让所有请求短路,直接返回失败的响应;一段时间后,断路器会变成半开状态,如果下一个请求成功了,就关闭断路器,反之就开启断路器。”

“那这个阈值具体是什么?”

“这里主要就要用到三个属性了:”小齐快速答道

(1)hystrix.command.default.circuitBreaker.requestVolumeThreshold(当在配置时间窗口内达到此数量的失败后,进行短路。默认20个)

简言之,10s内请求失败数量达到20个,断路器就会变成打开状态。

(2)hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds(短路多久以后开始尝试是否恢复,默认5s)

(3)hystrix.command.default.circuitBreaker.errorThresholdPercentage(出错百分比阈值,当达到此阈值后,开始短路。默认50%)

资源隔离

“非常正确!你知道Hystrix的底层原理吗?”

于是小齐祭出了官方的图:

Hystrix原理

“Hystrix主要使用的是RxJava来做异步请求,RxJava是一个异步框架,是对观察者模式的一个应用。Hystrix会把对每个微服务的请求放到线程池里面,具体分配到哪个线程池可以使用HystrixThreadPoolKey来指定”:

@HystrixCommand(threadPoolKey = "user-hello")
String getUserHello();

老张继续问:“那你知道为什么要有这个key吗?它是用来干嘛的?”小齐摇了摇头,表示自己还不知道。

“你看源码就知道了,Hystrix使用了一个ConcurrentHashMap来保存线程池。”

ConcurrentHashMap<String, HystrixThreadPool> threadPools

小齐心中出现了一个新的问题:那为什么我们需要多个线程池呢?

此时老张继续说道:“这个其实叫资源隔离。应用程序会被完全保护起来,即使依赖的一个服务出问题了,也不会影响到应用程序的其他部分。使用多个线程池就是一种资源隔离方式,也是默认的隔离方式。而且Hystrix底层是使用的RxJava,使用线程池可以让你很方便地实现异步操作。”

“那除了线程池隔离,还有其它隔离方式吗?”

“有的,Hystrix提供了两种隔离方式:线程池隔离和信号量(Semaphore)隔离。”

小齐说到:“参考了RedSpider技术社区的这篇文章,我知道Semaphore在多线程编程中经常发挥的是限制线程数量的作用,那它在这里相当于一个限流的作用?”

“是的,你可以参考这篇文章,信号量主要起一个限流的作用。如果信号量耗尽了,它就直接走「fallback流程」所以也能防止雪崩。但大多数情况,我们更倾向于使用线程池。”

fallback

“刚刚你提到了一个词叫‘fallback流程’?”

“是的,fallback翻译过来是‘回退’的意思,有时候我们也会称它‘「服务降级」’。”

“那什么时候会触发fallback呢?”

“其实你应该已经可以总结出来了,主要这五种情况会触发fallback:”

  • 执行超时

  • 执行过程抛出异常

  • 断路器打开状态

  • 线程池拒绝(池满后的拒绝策略)

  • 信号量拒绝(信号量耗完)

“那触发fallback后会发生什么?”

老张熟练的打开源码,并快速敲下了一个Demo。“这个你得看HystrixCommand这个类的源码和使用方式。”

class AuthCommand extends HystrixCommand<Boolean> {
  public Boolean run() {
    return authService.authenticate(user);
  }
  
  protected Boolean getFallback() {
    return true;
  }
}

“我们在使用Hystrix的时候,一般是继承HystrixCommand这个类,重写rungetFallback这两个方法。正常情况它是走run方法的。如果发生了fallback,它就会调用getFallback方法。”

小齐看着这段代码,问到:“这看起来有点麻烦,在Spring Cloud中,有更简单的使用方式吗?”

“当然。「在Spring Cloud中,Hystrix可以和OpenFeign无缝集成」。OpenFeign接口上的每个方法都会被Hystrix断路器包裹(这也是一种典型的AOP实现)。你可以在注解上配置fallback方法:”

@HystrixCommand(fallbackMethod = "getByIdFallback")
public String getById(String id) {...}

private String getByIdFallback(String id) {...}

“同时,你在@FeignClient这个注解里面可以看到两个属性:fallbackfallbackFactory,前者是指定一个类,通常这个类是继承当前接口的;后者是指定一个工厂类。具体示例代码如下:”

// Feign接口
@FeignClient(value = "service-user", fallback = UserClientImpl.class)
public interface UserClient {
    @GetMapping("hello")
    String getUserHello();
}

// 实现类
@Component
public class UserClientImpl implements UserClient {
    @Override
    public String getUserHello() {
        return "default user";
    }
}
// Feign接口
@FeignClient(value = "service-user", fallbackFactory = UserFallbackFactory.class)
public interface UserClient {
    @GetMapping("hello")
    String getUserHello();
}

// 工厂类
@Component
public class UserFallbackFactory implements FallbackFactory<UserClient> {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(UserFallbackFactory.class);

    @Override
    public UserClient create(Throwable cause) {
        LOGGER.info("the provider error is: {}", cause.getMessage());
        return new UserClient() {
            @Override
            public String getUserHello() {
                return "default user";
            }
        };
    }
}

“使用fallbackFactory的好处是可以得到异常信息,以便于自己做日志记录或者进一步的逻辑处理。”

感觉熔断这一块的知识点差不多理通了,小齐认真道谢,回到自己的位置继续撸代码……

关于作者

微信公众号:编了个程(blgcheng)

个人网站:https://yasinshaw.com

- 笔名Yasin,一个有深度,有态度,有温度的程序员。

- 阿里巴巴高级Java开发工程师;

- RedSpider技术社区发起人;

- 开源书籍《深入浅出Java多线程》第一作者。

你知道,这个公众号经常分享原创技术干货,关注了肯定不会后悔;

你知道,这个作者是个有趣的人,加个星标可以经常看到他写的文章;

你知道,转发并点击在看这篇文章的人都升职加薪了!

推荐阅读

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yasinshaw/article/details/106233608

智能推荐

【刷题专栏—突破思维】LeetCode 138. 随机链表的复制-程序员宅基地

文章浏览阅读2.4k次,点赞68次,收藏54次。随机链表的复制涉及到复制一个链表,该链表不仅包含普通的next指针,还包含random指针,该指针指向链表中的任意节点或空节点。

小程序第四章总结-程序员宅基地

文章浏览阅读1.5k次,点赞38次,收藏28次。style。

php+mysql+基于php+MYSQL的旅游景点攻略的设计与实现 毕业设计-附源码301216_php与mysql课题设计-程序员宅基地

文章浏览阅读318次,点赞5次,收藏5次。本课题研究的“基于PHP的旅游景点攻略网站”就是为了使游客更加方便、快捷的了解旅游景点以及攻略信息而设计的。采取Mysql作为后台数据的主要存储单元,采用Thinkphp框架、Redis技术进行业务系统的编码及其开发,实现了本系统的全部功能。该系统实现了网站内部的各种工作流程计算机管理化,其中包括网站简介、景点分析、景点信息、旅游攻略、旅游心得、作品获奖等功能。_php与mysql课题设计

第十一章:项目风险管理-0317_变异性风险-程序员宅基地

文章浏览阅读988次。一、概念1.风险的两个属性:概率和影响2.风险管理是通过识别,分析和应对风险来提高正面机会的概率,降低负面机会的概率。3.风险敞口:未加保护的风险4.单个项目风险和整体项目风险5.变异性风险:项目所依赖的关键条件或制约因素出现异常改变,就会导致变异性风险。黑天鹅事件6.模糊性风险:未彻底确定的风险7.整合式风险管理二、规划风险管理1.风险分类已知风险和未知风险内部风险和外部风险商业保险和可保险风险未知风险又分已知-未知风险和未知-未知风险商业风险是指正常的经营,技_变异性风险

PL/SQL连接Oracle数据库及优化_数据库设计与plsql开发和优化-程序员宅基地

文章浏览阅读383次。系统:windows7旗舰版 64位。oracle数据库服务器版本:oracle11g。oracle数据库客户端版本:64位 Version 12.2.0.1.0。PL/SQL版本:【Version 12.0.7.1837(64 bit)】。一、下载: 1、官网下载: 官网下载速度慢,不推荐,官网网址【https://www.allroundautoma..._数据库设计与plsql开发和优化

Github 2024-04-06Rust开源项目日报Top10_rust著名的开源项目-程序员宅基地

文章浏览阅读1.1k次,点赞5次,收藏20次。根据Github Trendings的统计,今日(2024-04-06统计)共有10个项目上榜。_rust著名的开源项目

随便推点

2021-06-23程序人生-Hello’s P2P_.o编译后的目标文件汇编-程序员宅基地

文章浏览阅读97次。这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入欢迎使用Markdown编辑器你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar_.o编译后的目标文件汇编

Linux安装Jdk11步骤_linux jdk11-程序员宅基地

文章浏览阅读329次。【代码】Linux安装Jdk11步骤。_linux jdk11

Oracle 创建 DBLink 的方法-程序员宅基地

文章浏览阅读55次。1、如果需要创建全局 DBLink,则需要先确定用户有创建 dblink 的权限: [c-sharp] view plaincopyprint? select * from user_sys_privs where privilege like upper('%DATABASE LINK%'); 如果没有,则需要使用 sysdba 角色给用..._oracle dblink创建

腾讯开源AppAgent,手机的大模型智能代理_腾讯 手机 模型-程序员宅基地

文章浏览阅读959次,点赞20次,收藏17次。而AppAgent采用了一种和RPA类似的方法,通过点击、滑动等模拟方式来操作APP,无需访问任何敏感数据,同时加上了大语言模型的理解和学习能力,使其效果更加出色以及增强适配性。也可以理解成大模型中的,人类反馈强化学习过程。据悉,AppAgent的功能与AutoGPT等智能代理类似,不依赖于操作系统的后台访问,而是通过UI界面进行点击、滑动等拟人化操作,与App进行交互操作。此外,视觉理解模块还可以利用机器视觉,进行图片对象和语义特征的提取,例如,识别图片内容、界面控件等,为后续的大脑、执行提供支持。_腾讯 手机 模型

【附学习笔记】为啥网络安全缺口这么大,还是这么缺网络安全工程师?-程序员宅基地

文章浏览阅读1.2k次,点赞28次,收藏30次。为啥网络安全缺口这么大,还是这么缺网络安全工程师?

c语言算法--栈--字符串处理1_c语言入栈存字符-程序员宅基地

文章浏览阅读46次。小明来对这个字符串进行操作,他会从头到尾检查这个字符串,如果发现有两个相同的字母并排在一起,就会把这两个字符都删掉。给定一个长度为n的字符串s,字符串由小写字母a…输出最后处理完成的字符串,有可能是空串。接下来一行一个长度为n的字符串s。你需要给出处理完成的字符串。直到没有相邻的相同字母。_c语言入栈存字符

推荐文章

热门文章

相关标签