Hystrix面试 - 基于 Hystrix 信号量机制实现资源隔离

Hystrix 里面核心的一项功能,其实就是所谓的资源隔离,要解决的最最核心的问题,就是将多个依赖服务的调用分别隔离到各自的资源池内。避免说对某一个依赖服务的调用,因为依赖服务的接口调用的延迟或者失败,导致服务所有的线程资源全部耗费在这个服务的接口调用上。一旦说某个服务的线程资源全部耗尽的话,就可能导致服务崩溃,甚至说这种故障会不断蔓延。

Hystrix 实现资源隔离,主要有两种技术:

  • 线程池
  • 信号量

默认情况下,Hystrix 使用线程池模式。

前面已经说过线程池技术了,这一小节就来说说信号量机制实现资源隔离,以及这两种技术的区别与具体应用场景。

信号量机制

信号量的资源隔离只是起到一个开关的作用,比如,服务 A 的信号量大小为 10,那么就是说它同时只允许有 10 个 tomcat 线程来访问服务 A,其它的请求都会被拒绝,从而达到资源隔离和限流保护的作用。

线程池与信号量区别

线程池隔离技术,并不是说去控制类似 tomcat 这种 web 容器的线程。更加严格的意义上来说,Hystrix 的线程池隔离技术,控制的是 tomcat 线程的执行。Hystrix 线程池满后,会确保说,tomcat 的线程不会因为依赖服务的接口调用延迟或故障而被 hang 住,tomcat 其它的线程不会卡死,可以快速返回,然后支撑其它的事情。

线程池隔离技术,是用 Hystrix 自己的线程去执行调用;而信号量隔离技术,是直接让 tomcat 线程去调用依赖服务。信号量隔离,只是一道关卡,信号量有多少,就允许多少个 tomcat 线程通过它,然后去执行。

适用场景

  • 线程池技术,适合绝大多数场景,比如说我们对依赖服务的网络请求的调用和访问、需要对调用的 timeout 进行控制(捕捉 timeout 超时异常)。
  • 信号量技术,适合说你的访问不是对外部依赖的访问,而是对内部的一些比较复杂的业务逻辑的访问,并且系统内部的代码,其实不涉及任何的网络请求,那么只要做信号量的普通限流就可以了,因为不需要去捕获 timeout 类似的问题。

信号量简单 Demo

业务背景里,比较适合信号量的是什么场景呢?

比如说,我们一般来说,缓存服务,可能会将一些量特别少、访问又特别频繁的数据,放在自己的纯内存中。

举个栗子。一般我们在获取到商品数据之后,都要去获取商品是属于哪个地理位置、省、市、卖家等,可能在自己的纯内存中,比如就一个 Map 去获取。对于这种直接访问本地内存的逻辑,比较适合用信号量做一下简单的隔离。

优点在于,不用自己管理线程池啦,不用 care timeout 超时啦,也不需要进行线程的上下文切换啦。信号量做隔离的话,性能相对来说会高一些。

假如这是本地缓存,我们可以通过 cityId,拿到 cityName。

public class LocationCache {private static Map<Long, String> cityMap = new HashMap<>();static {cityMap.put(1L, "北京");}/*** 通过cityId 获取 cityName** @param cityId 城市id* @return 城市名*/public static String getCityName(Long cityId) {return cityMap.get(cityId);}
}

写一个 GetCityNameCommand,策略设置为信号量。run() 方法中获取本地缓存。我们目的就是对获取本地缓存的代码进行资源隔离。

public class GetCityNameCommand extends HystrixCommand<String> {private Long cityId;public GetCityNameCommand(Long cityId) {// 设置信号量隔离策略super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetCityNameGroup")).andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE)));this.cityId = cityId;}@Overrideprotected String run() {// 需要进行信号量隔离的代码return LocationCache.getCityName(cityId);}
}

在接口层,通过创建 GetCityNameCommand,传入 cityId,执行 execute() 方法,那么获取本地 cityName 缓存的代码将会进行信号量的资源隔离。

@RequestMapping("/getProductInfo")
@ResponseBody
public String getProductInfo(Long productId) {HystrixCommand<ProductInfo> getProductInfoCommand = new GetProductInfoCommand(productId);// 通过command执行,获取最新商品数据ProductInfo productInfo = getProductInfoCommand.execute();Long cityId = productInfo.getCityId();GetCityNameCommand getCityNameCommand = new GetCityNameCommand(cityId);// 获取本地内存(cityName)的代码会被信号量进行资源隔离String cityName = getCityNameCommand.execute();productInfo.setCityName(cityName);System.out.println(productInfo);return "success";
}

转载来源:https://github.com/doocs/advanced-java/blob/master/docs/high-availability/hystrix-semphore-isolation.md

Hystrix面试 - 基于 Hystrix 信号量机制实现资源隔离相关推荐

  1. Hystrix面试 - 基于 Hystrix 线程池技术实现资源隔离

    Hystrix面试 - 基于 Hystrix 线程池技术实现资源隔离 上一讲提到,如果从 Nginx 开始,缓存都失效了,Nginx 会直接通过缓存服务调用商品服务获取最新商品数据(我们基于电商项目做 ...

  2. Hystrix面试 - 基于本地缓存的 fallback 降级机制

    Hystrix面试 - 基于本地缓存的 fallback 降级机制 Hystrix 出现以下四种情况,都会去调用 fallback 降级机制: 断路器处于打开的状态. 资源池已满(线程池+队列 / 信 ...

  3. Hystrix面试 - 基于 timeout 机制为服务接口调用超时提供安全保护

    Hystrix面试 - 基于 timeout 机制为服务接口调用超时提供安全保护 一般来说,在调用依赖服务的接口的时候,比较常见的一个问题就是超时.超时是在一个复杂的分布式系统中,导致系统不稳定,或者 ...

  4. Hystrix面试 - 基于 request cache 请求缓存技术优化批量商品数据查询接口

    Hystrix面试 - 基于 request cache 请求缓存技术优化批量商品数据查询接口 Hystrix command 执行时 8 大步骤第三步,就是检查 Request cache 是否有缓 ...

  5. Hystrix面试 - 深入 Hystrix 线程池隔离与接口限流

    Hystrix面试 - 深入 Hystrix 线程池隔离与接口限流 前面讲了 Hystrix 的 request cache 请求缓存.fallback 优雅降级.circuit breaker 断路 ...

  6. Hystrix面试 - 深入 Hystrix 执行时内部原理

    Hystrix面试 - 深入 Hystrix 执行时内部原理 前面我们了解了 Hystrix 最基本的支持高可用的技术:资源隔离 + 限流. 创建 command: 执行这个 command: 配置这 ...

  7. Hystrix面试 - 用 Hystrix 构建高可用服务架构

    Hystrix面试 - 用 Hystrix 构建高可用服务架构 Hystrix 是什么? 在分布式系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是依赖服务,有的时候某些依赖服务出现故障也 ...

  8. Hystrix面试 - 深入 Hystrix 断路器执行原理

    Hystrix面试 - 深入 Hystrix 断路器执行原理 RequestVolumeThreshold HystrixCommandProperties.Setter().withCircuitB ...

  9. 亿级流量电商详情页系统实战-38.hystrix与高可用系统架构:资源隔离+限流+熔断+降级+运维监控

    1.前言 前半部分,专注在高并发这一块,缓存架构,承载高并发,在各种高并发导致的令人崩溃/异常的场景下,运行着缓存架构,高可用性,在各种系统的各个地方有乱七八糟的异常和故障的情况下,整套缓存系统还能继 ...

最新文章

  1. ESP8266的一个小问题
  2. python三级联动菜单_详解element-ui级联菜单(城市三级联动菜单)和回显问题
  3. Winform中封装DevExpress的MarqueeProgressBarComtrol实现弹窗式进度条效果
  4. TypeScript方法的定义
  5. MySQL行转列完整SQL示例
  6. 华为鸿蒙全能家居,能兑现多少?华为智慧屏十年不过时,用鸿蒙理念做智能家居...
  7. 三分钟Docker-推送本地镜像到仓库
  8. jquery 表单验证
  9. 百度-提高效率的高级搜索语法
  10. solidity合约详解
  11. 2、Shiro的认证
  12. python3线程池爬虫_python3多线程爬虫中如何变量?
  13. java大学实用教程(第四版)_Java大学实用教程(第4版)
  14. 快速隐藏/取消隐藏工作表
  15. Java游戏神秘岛,【寻找高玩】服务端整合问题
  16. flannel 介绍(UTP、VXLAN、Host Gateway模式详解)
  17. win10插入耳机没声音,如何设置声音
  18. 第三部分 :简单句的补充(限定词/形容词/介词短语)
  19. Revit建模中如何快速画好幕墙?
  20. python 安装TFLearn模块

热门文章

  1. Node.js入门 - 永恒的Hello World!
  2. Linux内核中container_of宏的理解
  3. centos6.8 安装python3.6
  4. numpy+pandas+matplotlib画箱形图
  5. apt-get与dpkg常用命令
  6. C++——构建单链表的方法
  7. OPENWRT的串口初试
  8. 草稿 断开始datagrewvies 01
  9. 演练 看不见的硬币 1002
  10. 爬虫-urlparse与urlsplit