引子

幸福很简单:

今天项目半年规划被通过,终于可以早点下班。先坐公交,全程开着灯,买了了几天的书竟然有时间看了。半小时后,公交到站,换乘大巴车。车还等着上人的功夫,有昏暗的灯光,可以继续看会儿书。过会儿车跑起来了,灯关了。我合上书,头靠着车窗,眼睛看着窗外,脑子想着怎么把书里的东西用到工作中进行知行合一。想着想着出了神,突然听到报我们小区的名字,赶紧下了车,刚好没坐过站。

回家一看,那个声称今天会下班很晚的人果然比我还晚。边洗漱边想着上周末,和小鲜肉一起看了动画片。小鲜肉非要我买培根。因为他想像动画片里一样用两个荷包蛋做眼睛,培根做嘴巴。于是晚上睡觉的时候,我下单买了培根,早上7点快递送了来。我就和小鲜肉一起做早餐。他说想吃糖口味的蛋,于是我们改良了一下把荷包蛋眼睛变成摊鸡蛋大脸。本来小鲜肉说只要一片培根。我想一包都打开了,干脆一起煎了。结果因为是自己动手,小鲜肉只好多吃,结果吃培根吃的一天都感觉油腻。想着这周,一包培根要分到一天三顿里,加上配菜,和小鲜肉一起做出三种花样来。关键是小鲜肉到周末比我还忙,8点开始跆拳道,一天各种兴趣班。他想自己做早餐得早起。

洗漱完,吹完头发。看看洗澡水又烧的差不多了。这次终于轮到我发那条消息:“洗澡水够了”。然后拔掉烧水的电源确保安全。竟然有时间贴上面膜再看会书,满足。

原来幸福就是:其实很忙,但是能挤出点时间干点自己的事情,提升提升自己。

hystrix隔离原理

hystrix可以完成隔离、限流、熔断、降级这些常用保护功能。这四个功能可以这么来理解:

hystrix的隔离分为线程池隔离和信号量隔离。

信号量隔离原理

信号量隔离就是hystrix的限流功能。虽然名字叫隔离,实际上它是通过信号量来实现的。而信号量说白了就是个计数器。计数器计算达到设定的阈值,直接就做异常处理。

ratelimiter的令牌桶算法和漏桶算法,都是直接对请求量来计数。只是令牌桶算法可以将前面一段时间没有用掉的请求量允许余额拿过继续用。而漏桶算法一段时间就允许这么多,前面没用掉的也不能用了。

而hystrix信号量隔离限制的是tomcat等Web容器线程数,一段时间仅仅能支持这么多。多余的请求再来请求线程资源,就被拒绝了。所以是一种“曲径通幽”的限流方式。因为实际是通过隔离了部分容器线程资源,也算是一种隔离方式。

线程池隔离原理

信号量隔离只是起了个限制作用,它的保护能力有限:如果下游服务有问题,长时间不返回结果。本身信号量隔离对这个单个请求是起不到任何作用的。它只能限制这样的请求太多了就拒绝,不让整个服务挂。

为了解决这个问题,hystrix又产生了线程池隔离。这种隔离方式是通过引入额外线程的方式。对原来的web容器线程做管理控制:如果一个线程超时未返回,则熔断。既然引入额外的线程就涉及线程池管理、线程的上下文切换这些额外的开销。所以相比信号量隔离,线程池隔离成本更高。

熔断原理

隔离不但可以做保护,还可以做统计:成功了多少失败了多少。既然有统计数据了,它就可以进一步处理:失败太多了,说明现在有问题,执行完了再发现失败太浪费资源,干脆就先不让worker线程执行了。过段时间再试试。这就是断路器模式,也就是熔断的原理。

降级原理

任何异常需要熔断的场景,为的都是反正都是错,干脆把这资源省了。直接返回一个预定的错误。这个熔断后返回设定错误的过程就是降级。

资源保护的流程

从上面来看所谓的hystrix的四大功能:限流、隔离、熔断和降级。只是完成了一整个对资源保护的生命周期。来看看对应的BPMN流程图:

信号量隔离的流程

线程池隔离的流程

现在大家请回答我一个问题:我上面说的是对的吗?

hystrix隔离验证

采用淘金式的思维,不要别人说什么都信。网上很多技术博客里说的都是错的。我的文章也有可能是错的,事实上我说的很多东西都带有自己脑补的成分。

既然不确定是否是对的,就要去验证。先验证

1>hystrix隔离确实能限制资源

2>信号量隔离采用的Web容器的线程池,而线程池隔离采用的是自己独立的线程池。

本次验证,Web容器使用的是spring boot内嵌的jetty。代码已经上传github:

https://github.com/xiexiaojing/yuna

信号量隔离验证

 

隔离hystrix配置

import com.netflix.hystrix.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.config.ConfigurableBeanFactory;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
@Component@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)public class DemoHystrixCommand extends HystrixCommand<String> { private static final Logger logger = LoggerFactory.getLogger(DemoHystrixCommand.class); private String poolName;
public DemoHystrixCommand() { super(Setter.withGroupKey( //服务分组 HystrixCommandGroupKey.Factory.asKey("DemoGroup")) //线程分组 .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("DemoPool")) //线程池配置 .andThreadPoolPropertiesDefaults( HystrixThreadPoolProperties.Setter() .withCoreSize(2) .withKeepAliveTimeMinutes(5) .withMaxQueueSize(2) .withQueueSizeRejectionThreshold(10)) //线程池隔离 .andCommandPropertiesDefaults( HystrixCommandProperties.Setter() .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE) ) ); }
@Override protected String run() throws Exception { logger.info(poolName + ":我伤心我无奈,可是我默默等待"); TimeUnit.MILLISECONDS.sleep(100); return poolName + "-run:缘分就是一生的等待"; }
public void setPoolName(String poolName) { this.poolName = poolName; }}

调用方


import com.brmayi.yuna.util.DemoHystrixCommand;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestControllerpublic class HystrixController { @Autowired private ApplicationContext applicationContext;
@GetMapping("/hystrix") public String hystrix(String poolName) throws Exception { DemoHystrixCommand demoHystrixCommand = applicationContext.getBean(DemoHystrixCommand.class); demoHystrixCommand.setPoolName(poolName); return demoHystrixCommand.execute(); }}

验证

多点几次

多点几次

看日志,日志前缀里Web容器的其他日志线程号和请求hystrix的线程号规则一致,可说明是Web容器的线程。

注意看,不管是倩倩还是萍儿,它们的线程数都没有超过最大线程数

线程池隔离验证

只要将隔离hystrix配置

HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE

改成

HystrixCommandProperties.ExecutionIsolationStrategy.THREAD

重启后重复上面验证步骤

看线程池名变成了隔离hystrix配置的线程名规则!并且不管是倩倩还是萍儿,它们的线程数都没有超过最大线程数。

以上实验说明

1>hystrix隔离确实能限制资源

2>信号量隔离采用的Web容器的线程池,而线程池隔离采用的是自己独立的线程池。

成立。

其他部分限于篇幅,我就不验证了。这里用到了打日志的方法验证线程池情况。如果在生产环境,实际上我们是需要对线程池情况做监控的。可以使用java.lang.management包里的工具注册监控。我们平时使用falcon这样的工具来查看,原理也是先通过java.lang.management包里的工具注册上报信息到服务端采集的。如果自己想查看监控结果,可以用jdk自带的jvisualvm安装一个com-sun-tools-visualvm-modules-mbeans.nbm插件来看。

总结

本篇文章的验证部分很粗糙,限于篇幅,没有把所有需要验证的点覆盖全。想验证我花的hystrix资源保护生命周期的图,至少要结合源码和验证两方面。先当留作业了,有时间我把详细过程补上。

hystrix线程池隔离的原理与验证的更多相关文章

  1. 危险的Hystrix线程池

    本文介绍Hystrix线程池的工作原理和参数配置,指出存在的问题并提供规避方案,阅读本文需要对Hystrix有一定的了解. 文本讨论的内容,基于hystrix 1.5.18: <dependen ...

  2. Hystrix入门与分析(二):依赖隔离之线程池隔离

    1.依赖隔离概述 依赖隔离是Hystrix的核心目的.依赖隔离其实就是资源隔离,把对依赖使用的资源隔离起来,统一控制和调度.那为什么需要把资源隔离起来呢?主要有以下几点: 1.合理分配资源,把给资源分 ...

  3. 基于hystrix的线程池隔离

    hystrix进行资源隔离,其实是提供了一个抽象,叫做command,就是说,你如果要把对某一个依赖服务的所有调用请求,全部隔离在同一份资源池内 对这个依赖服务的所有调用请求,全部走这个资源池内的资源 ...

  4. 一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 31.线程池复用的原理 32.spring是什么? 33.对Aop的理解 34.对IOC的理解 35.BeanFactor ...

  5. 深入源码分析Java线程池的实现原理

    程序的运行,其本质上,是对系统资源(CPU.内存.磁盘.网络等等)的使用.如何高效的使用这些资源是我们编程优化演进的一个方向.今天说的线程池就是一种对CPU利用的优化手段. 通过学习线程池原理,明白所 ...

  6. Hystrix线程池配置

    Hystrix配置文件配置 断路器: hystrix.command.default.circuitBreaker.requestVolumeThreshold(当在配置时间窗口内达到此数量的失败后, ...

  7. 基于C++11实现线程池的工作原理

    目录 基于C++11实现线程池的工作原理. 简介 线程池的组成 1.线程池管理器 2.工作线程 3.任务接口, 4.任务队列 线程池工作的四种情况. 1.主程序当前没有任务要执行,线程池中的任务队列为 ...

  8. 21.线程池ThreadPoolExecutor实现原理

    1. 为什么要使用线程池 在实际使用中,线程是很占用系统资源的,如果对线程管理不善很容易导致系统问题.因此,在大多数并发框架中都会使用线程池来管理线程,使用线程池管理线程主要有如下好处: 降低资源消耗 ...

  9. 线程池续:你必须要知道的线程池submit()实现原理之FutureTask!

    前言 上一篇内容写了Java中线程池的实现原理及源码分析,说好的是实实在在的大满足,想通过一篇文章让大家对线程池有个透彻的了解,但是文章写完总觉得还缺点什么? 上篇文章只提到线程提交的execute( ...

随机推荐

  1. 国产化之路-麒麟V10操作系统安装.net core 3.1 sdk

    随着芯片国产化,操作系统国产化,软件国产化的声浪越来越高,公司也已经把开发项目国产化提上了日程,最近搞来了台长城的国产化电脑主机,用来搞试验,安装的是麒麟V10的操作系统,国产化折腾之路就此开始,用的 ...

  2. BUU reverse xxor

    下载下来的是个elf文件,因为懒得上Linux,直接往IDA里扔, 切到字符串的那个窗口,发现Congratulation!,应该是程序成功执行的表示, 双击,按'x',回车跟入 找到主函数: 1 _ ...

  3. Linux里面的压缩和解压类指令

    gzip/gunzip 指令 ( .gz  不能压缩目录) gzip 用于压缩文件, gunzip 用于解压的 . gzip gzip命令用来压缩文件.gzip是个使用广泛的压缩程序,文件经它压缩过后 ...

  4. SpringBoot-03-JSR303数据校验和多环境切换

    3.3 JSR303数据校验 先看如何使用 ​ Springboot中可以用@Validated来校验数据,如果数据异常则统一抛出异常,方便异常中心统一处理. ​ 这里我们写个注解让name只支持Em ...

  5. 分享一些比较好用的(免费)网站及推荐理由 SMARK

    分享一些比较好用的(免费)网站及推荐理由 --By SMARK 资源类 这里面是一些有供下载的资源的网站等 视频 片库 内容怎么样有待考证 蓝光网 看着还行, 打赏收入 预告片世界 还行, 收入有待考 ...

  6. LeetCode刷题的一点个人建议和心得

    目录 1.    为什么我们要刷LeetCode? 2.    LeetCode的现状和问题 3.    本文的初衷 4.    LeetCode刷题建议 4.1入门数据结构,打基础阶段 4.2 建立 ...

  7. three.js学习5_渲染器

    THREE.WebGLRenderer WebGL Render 用WebGL渲染出你精心制作的场景 介绍 在之前的介绍中, 已经介绍过场景, 相机, 光源, 有了这些后, 就可以形成一个可观的三维展 ...

  8. 获取豆瓣读书所有热门标签并保存到mongodb数据库

    目标url:https://book.douban.com/tag/?view=type&icn=index-sorttags-all 目的:抓取所有标签名称(tag_name),标签链接(t ...

  9. python排序算法总结和实现

    ------------------希尔排序------------- 一直没搞懂希尔排序怎么搞得 def Shell_sort(L): step = len(L)/2 while step > ...

  10. 一文搞懂PV、UV、VV、IP及其关系与计算

    写在前面 十一长假基本上过去了,很多小伙伴在假期当中还是保持着持续学习的心态,也有不少小伙伴在微信上问我,让我推送相关的文章.这个时候,我都是抽空来整理小伙伴们的问题,然后,按照顺序进行推文. PS: ...