微服务框架下,一个服务依赖于很多服务。在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素,比如网络连接变慢,资源突然繁忙,暂时不可用,服务脱机等,一个被调用服务出问题可能导致调用者不能正常调用其他服务。我们要构建稳定、可靠的分布式系统,就必须要有一套容错方法来应对这些情况。

Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程池隔离、信号量隔离、熔断(Circuit Breaker)、降级回退(Fallback),还支持请求缓存(Request Caching)、请求合并(Request Collapsing)等。应用场景如网关服务调用订单服务、商品服务、用户服务。

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.

1 基本概念

Dependency
指的是在当前服务中所调用的服务,如若当前服务为网关服务,则其所调用的订单服务是其一个Dependency。
 
HystrixCommand、HystrixObservableCommand
Hystrix中用命令模式来包装对所依赖的服务的调用,如将对订单服务的调用包装成一个commond,示例:

public class GetOrderCommand extends HystrixCommand<List> {

    OrderService orderService;

    public GetOrderCommand(String name){
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ThreadPoolTestGroup"))
.andCommandKey(HystrixCommandKey.Factory.asKey("testCommandKey"))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(name))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withExecutionTimeoutInMilliseconds(5000)
)
.andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties.Setter()
.withMaxQueueSize(10) //配置队列大小
.withCoreSize(2) // 配置线程池里的线程数
)
);
} @Override
protected List run() throws Exception {
return orderService.getOrderList();
} public static class UnitTest {
@Test
public void testGetOrder(){
// new GetOrderCommand("hystrix-order").execute();
Future<List> future =new GetOrderCommand("hystrix-order").queue();
} }
}

每个服务对应的commond都有单独的线程池来负责执行。这样当调用者调用多个服务时,某个服务发生异常不会影响调用者对其他服务的调用。

Commond可同步或异步执行:execute()、queue()、observe()、toObservable()

2 内部执行流程

3 容错技术

3.1 依赖隔离(Dependency Isolation)

依赖隔离是指采用某种处理方式使得对一个依赖的调用阻塞时不影响调用方对其他依赖的调用。

显然,最简单的方式是每次调用都起一个新线程执行调用处理,这理论上是可行的,但实际上不会被采用,因为很耗费资源(频繁创建线程、可创建线程数有限等)。解决:仍采用多线程,但需要进一步改造——限制可创建的线程数,有线程池、信号量方式。

3.1.1 线程池隔离

每个依赖的服务的Client(如订单服务的OrderClient)都被包装成HystrixCommand或HystrixObservableCommand。

commond相当于是目标服务的Client的代理,每个服务对应一个commond,每个common内部有个线程池,用来负责执行对目标服务的调用。这样的优点之一是:在调用者方面,一个服务调用阻塞(如超时)时不会影响对其他服务的调用,将影响范围限制在了一个服务内;通过线程池大小控制并发能力。

the isolation provided by thread pools allows for the always-changing and dynamic combination of client libraries and subsystem performance characteristics to be handled gracefully without causing outages.

示意图:

线程池技术本质上与数据库等的连接池类似,一方面用于复用线程/连接以免重复创建线程/连接、另一方面用于限制对服务端的并发访问数。这里的线程池隔离与数据库连接池的区别在于:前者由于要对接多个后端服务而后者专为一个后端服务(数据库),故前者需要为每个服务对应一个线程池而后者只需要一个连接池,两者本质上是一样的。(其实很多技术本质上是一样的,透过现象看本质!)

3.1.2 信号量隔离

此模式使用的场景是被调用的依赖是不耗时的操作时(如从当前进出内存取数据等而非进行RPC)。该模式下每次调用commond时直接用当前线程来执行对目标服务的调用,因此实际上是做不到依赖隔离的——当前服务同时调用多个服务时一个服务的阻塞会影响对其他服务的调用。其主要作用是控制对一个依赖的并发调用个数,所以称counter更贴切。

线程池隔离与信号量隔离的区别:

  • THREAD — it executes on a separate thread and concurrent requests are limited by the number of threads in the thread-pool。(HystrixCommand推荐用此)
  • SEMAPHORE — it executes on the calling thread and concurrent requests are limited by the semaphore count。(HystrixOvservableCommand推荐用此)

3.2 断路器(Circuit Breaker)

6个核心参数:

1、circuitBreaker.enabled

是否启用熔断器,默认是TURE。

2、circuitBreaker.forceOpen

熔断器强制打开,始终保持打开状态。默认值FLASE。

3、circuitBreaker.forceClosed

熔断器强制关闭,始终保持关闭状态。默认值FLASE。

4、circuitBreaker.errorThresholdPercentage

设定错误百分比,默认值50%,例如一段时间(10s)内有100个请求,其中有55个超时或者异常返回了,那么这段时间内的错误百分比是55%,大于了默认值50%,这种情况下触发熔断器-打开。

5、circuitBreaker.requestVolumeThreshold

默认值20。意思是至少有20个请求才进行errorThresholdPercentage错误百分比计算。比如一段时间(10s)内有19个请求全部失败了。错误百分比是100%,但熔断器不会打开,因为requestVolumeThreshold的值是20.。

6、circuitBreaker.sleepWindowInMilliseconds

半开试探休眠时间,默认值5000ms。当熔断器开启一段时间之后比如5000ms,会尝试放过去一部分流量进行试探,确定依赖服务是否恢复。

3.3 降级回退(Fallback)

即指定在调用目标服务失败时进行怎样的处理,通常是返回个默认值。

3.4 请求合并(Request Collapsing)

3.5 请求缓存(Request Caching)

4 弊端

牛逼吹了一堆,实际使用时发现的弊端。

关于熔断功能:熔断有connectionTimeout、readTimeout,前者为建立连接过程的超时时间、后者为连接成功后发起请求到收到调用结果的超时时长。启用熔断后,发起服务调用时,若达到了任一个超时时间则调用方会认为服务不可用,然而若达到了readTimeout,实际上可能被调用服务已经在执行,而调用方却认为服务不可用了,这就会造成不同服务间的数据不一致,除非调用方在认为服务不可用时对被调用服务进行回滚(分布式事务等)。因此readTimeout是个很重要的参数,定太短了会导致不同服务上的数据不一致,然而这个参数通常不好定,特别是服务调用链很长时更难以确定该设什么值。

5 参考资料

https://github.com/Netflix/Hystrix/wiki/How-it-Works?spm=a2c4e.11153940.blogcont183592.6.4ec85c9dkbFMeW

https://www.jianshu.com/p/3e11ac385c73

容错框架之Hystrix小记的更多相关文章

  1. Dubbo服务容错(整合hystrix)

    简介:Hystrix旨在通过控制那些访问远程系统.服务和第三方库的节点从而对延迟和故障提供更强大的容错能力,Hystrix具备拥有回退机制和断路器功能的线程和信号隔离.请求缓存和请求打包以及监控和配置 ...

  2. SpringCloud初体验:三、Feign 服务间调用(FeignClient)、负载均衡(Ribbon)、容错/降级处理(Hystrix)

    FeignOpenFeign Feign是一种声明式.模板化的HTTP客户端. 看了解释过后,可以理解为他是一种 客户端 配置实现的策略,它实现 服务间调用(FeignClient).负载均衡(Rib ...

  3. SpringCloud系列之服务容错保护Netflix Hystrix

    1. 什么是雪崩效应? 微服务环境,各服务之间是经常相互依赖的,如果某个不可用,很容易引起连锁效应,造成整个系统的不可用,这种现象称为服务雪崩效应. 如图,引用国外网站的图例:https://www. ...

  4. SpringCloud之Hystrix:集群容错框架

    分布式环境中,可能会有一些被依赖的服务会失效,影响系统的稳定运行.Hystrix通过添加延迟阈值以及容错的逻辑,以控制分布式系统间组件的交互.Hystrix通过隔离服务间的访问点.停止它们之间的级联故 ...

  5. 微服务容错限流Hystrix入门

    为什么需要容错限流 复杂分布式系统通常有很多依赖,如果一个应用不能对来自依赖 故障进行隔离,那么应用本身就处在被拖垮的风险中.在一个高流量的网站中,某个单一后端一旦发生延迟,将会在数秒内导致 所有应用 ...

  6. 遗传算法框架GAFT优化小记

    前言 前段时间一直在用自己写的遗传算法框架测试算法在优化力场参数的效果,但是跑起来效率很慢,因为适应度函数需要调用多次力场程序计算能量,但是还是比我预想中的慢我也没有及时对程序进行profiling和 ...

  7. 【Spring Cloud】服务容错保护:Hystrix(四)

    一.雪崩效应 在微服务架构中,由于服务和服务之间可以互相调用,一项工作的完成可能会依赖调用多个微服务模块,但由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问题,调用这个服务就 ...

  8. 2.4容错保护:Hystrix

    在ribbon使用断路器 改造serice-ribbon 工程的代码,首先在pox.xml文件中加入spring-cloud-starter-hystrix的起步依赖: 引入 <dependen ...

  9. Spring Cloud组件使用/配置小记

    仅使用,无多少技术含量,权记于此以备忘. 微服务架构下的主要组件 服务注册组件:Consul.Etcd等 网关:Zuul.Spring Cloud Gateway等 容错框架:Hystrix 负载均衡 ...

随机推荐

  1. C++:class

    class 类是C++的一个重要概念,也是面向对象的一个重要内容.类的行为类似结构体,但功能比结构体的更强大.类是定义该类对象的一个模板,它告诉我们,一个类应该具有什么内容. 声明.定义 类用关键字c ...

  2. 博客中新浪图床 迁移至 阿里云的OSS

    前言 因为之前有个新浪的图床,还挺好用,而且免费,自己博客的图片上传到其上面也挺方便的,但是,前几周吧,突然图片就不能访问了,之前本来是想通过添加 meta 头来解决的,但是发现没有效果.于是就自己搞 ...

  3. [Node.js] TypeScript 实现 sleep 函数

    看过不少网友的文章, 有各种方法, 但我想要的是一个能线性执行的sleep函数. /** * 等待指定的时间 * @param ms */ static async sleep(ms: number) ...

  4. WEB网站发布服务器IIS报错问题终极解决方案,查到问题点

    4本次错误webservice发布新服务器后,出现此错误. 解决方法: 找到dmp文件 dmp文件是啥?自己百度.简单的说就是黑匣子,记录程序崩溃前的操作,那么如何找到这个黑匣子呢? 1.启动 Win ...

  5. Python - 常规操作Excel - 第二十六天

    前言 作为一名资深程序员,通过代码熟练操作Excel是必不可少的技能,本章主要讲解Python通过openpyxl第三方库(官方文件说明)对Excel进行操作,使Excel程序化操作更为简单快捷. o ...

  6. Python - 数据结构 - 第十五天

    Python 数据结构 本章节我们主要结合前面所学的知识点来介绍Python数据结构. 列表 Python中列表是可变的,这是它区别于字符串和元组的最重要的特点,一句话概括即:列表可以修改,而字符串和 ...

  7. 章节十四、3-执行JavaScript命令

    一.网页页面都是由html+css和javaScript组成的,如果页面中没有javaScript的存在,就不会有操作动作的执行,例如页面上你点击的按钮或者链接都离不开javaScript.(这一节不 ...

  8. 深入理解JVM虚拟机(一):JVM运行时数据区

    概述: JVM将内存的管理进行封装,使得开发人员不必关心内存申请.释放操作.但是在高级程序开发.复杂业务场景开发的时候,如果出现内存溢出的情况,对于开发人员而言就很难去分析出原因.所以还是很有必要去了 ...

  9. python 的三元操作符

    条件表达式(三元操作符)    1.有了这个三元操作符的条件表达式,你可以使用一条语句来完成下面的条件判断和赋值操作: x,y=4,5 if x<y: temp = x else: temp = ...

  10. Anslble 部署安装

    安装文档:https://ansible-tran.readthedocs.io/en/latest/docs/intro_configuration.html https://docs.ansibl ...