为什么需要容错限流

  • 复杂分布式系统通常有很多依赖,如果一个应用不能对来自依赖 故障进行隔离,那么应用本身就处在被拖垮的风险中。在一个高流量的网站中,某个单一后端一旦发生延迟,将会在数秒内导致 所有应用资源被耗尽(一个臭鸡蛋影响一篮筐)。
  • 如秒杀、抢购、双十一等场景,在某一时间点会有爆发式的网络流量涌入,如果没有好的网络流量限制,任由流量压到后台服务实例,很有可能造成资源耗尽,服务无法响应,甚至严重的导致应用崩溃。

Hystrix是什么

Hystrix 能使你的系统在出现依赖服务失效的时候,通过隔离系统所依赖的服务,防止服务级联失败,同时提供失败回退机制,更优雅地应对失效,并使你的系统能更快地从异常中恢复。

Hystrix能做什么

  • 在通过第三方客户端访问(通常是通过网络)依赖服务出现高延迟或者失败时,为系统提供保护和控制
  • 在分布式系统中防止级联失败
  • 快速失败(Fail fast)同时能快速恢复
  • 提供失败回退(Fallback)和优雅的服务降级机制
  • 提供近似实时的监控、报警和运维控制手段

Hystrix设计原则

  • 防止单个依赖耗尽容器(例如 Tomcat)内所有用户线程
  • 降低系统负载,对无法及时处理的请求快速失败(fail fast)而不是排队
  • 提供失败回退,以在必要时让失效对用户透明化
  • 使用隔离机制(例如『舱壁』/『泳道』模式,熔断器模式等)降低依赖服务对整个系统的影响
  • 针对系统服务的度量、监控和报警,提供优化以满足近似实时性的要求
  • 在 Hystrix 绝大部分需要动态调整配置并快速部署到所有应用方面,提供优化以满足快速恢复的要求
  • 能保护应用不受依赖服务的整个执行过程中失败的影响,而不仅仅是网络请求

Hystrix设计思想来源

舱壁隔离模式

货船为了进行防止漏水和火灾的扩散,会将货仓分隔为多个,当发生灾害时,将所在货仓进行隔离就可以降低整艘船的风险。

断路器模式

熔断器就像家里的保险丝,当电流过载了就会跳闸,不过Hystrix的熔断机制相对复杂一些。

熔断器开关由关闭到打开的状态转换是通过当前服务健康状况和设定阈值比较决定的.

  • 当熔断器开关关闭时,请求被允许通过熔断器。如果当前健康状况高于设定阈值,开关继续保持关闭。如果当前健康状况低于设定阈值,开关则切换为打开状态。
  • 当熔断器开关打开时,请求被禁止通过。
  • 当熔断器开关处于打开状态,经过一段时间后,熔断器会自动进入半开状态,这时熔断器只允许一个请求通过。当该请求调用成功时,熔断器恢复到关闭状态。若该请求失败,熔断器继续保持打开状态, 接下来的请求被禁止通过。

Hystrix工作流程

官网原图

中文版

流程说明

  1. 每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中.
  2. 执行execute()/queue做同步或异步调用.
  3. 当前调用是否已被缓存,是则直接返回结果,否则进入步骤 4
  4. 判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤 8,进行降级策略,如果关闭进入步骤 5
  5. 判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤 6
  6. 调用HystrixCommand的run方法.运行依赖逻辑
  • 6.1. 调用是否出现异常,否:继续,是进入步骤8,
  • 6.2. 调用是否超时,否:返回调用结果,是进入步骤8
  1. 搜集5、6步骤所有的运行状态(成功, 失败, 拒绝,超时)上报给熔断器,用于统计从而判断熔断器状态
  2. getFallback()降级逻辑.四种触发getFallback调用情况(图中步骤8的箭头来源):

    返回执行成功结果

两种资源隔离模式

线程池隔离模式

使用一个线程池来存储当前的请求,线程池对请求作处理,设置任务返回处理超时时间,堆积的请求堆积入线程池队列。这种方式需要为每个依赖的服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队里慢慢处理)。

信号量隔离模式

使用一个原子计数器(或信号量)来记录当前有多少个线程在运行,请求来先判断计数器的数值,若超过设置的最大线程个数则丢弃改类型的新请求,若不超过则执行计数操作请求来计数器+1,请求返回计数器-1。这种方式是严格的控制线程且立即返回模式,无法应对突发流量(流量洪峰来临时,处理的线程超过数量,其他的请求会直接返回,不继续去请求依赖的服务)。

线程池隔离模式 VS 信号量隔离模式

Hystrix主要配置项



快速上手

pom.xml

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.12</version>
</dependency>

HystrixConfig

@Configuration
public class HystrixConfig { /**
* 声明一个HystrixCommandAspect代理类,现拦截HystrixCommand的功能
*/
@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
} }

HelloService

@Service
public class HelloService { @HystrixCommand(fallbackMethod = "helloError",
commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000"),
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "2")},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "5"),
@HystrixProperty(name = "maximumSize", value = "5"),
@HystrixProperty(name = "maxQueueSize", value = "10")
})
public String sayHello(String name) {
try {
Thread.sleep( 15000 );
return "Hello " + name + " !";
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
} public String helloError(String name) {
return "服务器繁忙,请稍后访问~";
} }

启动类

@SpringBootApplication
@RestController
public class HystrixSimpleApplication { @Autowired
private HelloService helloService; public static void main(String[] args) {
SpringApplication.run( HystrixSimpleApplication.class, args );
} @GetMapping("/hi")
public String hi(String name) {
return helloService.sayHello( name );
} }

测试

访问 http://localhost:80809/hi?name=zhangsan

curl -X GET -d 'name=zhangsan' http://localhost:8080/hi

返回

服务器繁忙,请稍后访问~

源码

https://github.com/gf-huanchupk/SpringCloudLearning/tree/master/chapter16

参考

https://github.com/Netflix/Hystrix/wiki

https://blog.51cto.com/snowtiger/2057092

欢迎扫码或微信搜索公众号《程序员果果》关注我,关注有惊喜~

微服务容错限流Hystrix入门的更多相关文章

  1. 微服务熔断限流Hystrix之流聚合

    简介 上一篇介绍了 Hystrix Dashboard 监控单体应用的例子,在生产环境中,监控的应用往往是一个集群,我们需要将每个实例的监控信息聚合起来分析,这就用到了 Turbine 工具.Turb ...

  2. 微服务熔断限流Hystrix之Dashboard

    简介 Hystrix Dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard可以直观地看到各Hystrix Command的请求响应时间,请求成功率等数据 ...

  3. 微服务组件--限流框架Spring Cloud Hystrix分析

    Hystrix的介绍 [1]Hystrix是springCloud的组件之一,Hystrix 可以让我们在分布式系统中对服务间的调用进行控制加入一些调用延迟或者依赖故障的容错机制. [2]Hystri ...

  4. Hystrix微服务容错处理及回调方法源码分析

    前言 在 SpringCloud 微服务项目中,我们有了 Eureka 做服务的注册中心,进行服务的注册于发现和服务治理.使得我们可以摒弃硬编码式的 ip:端口 + 映射路径 来发送请求.我们有了 F ...

  5. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---先让程序跑起来(一) 写下此文章只为了记录Surging微服务学习过程,并且分享给广大想学习surging的基友,方便广大 ...

  6. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二) 先上项目解决方案图: 以上可以看出项目结构可以划分为4大块,1是surging的核心底层,2,3,4都可以 ...

  7. Go微服务容错与韧性(Service Resilience)

    Service Resilience是指当服务的的运行环境出现了问题,例如网络故障或服务过载或某些微服务宕机的情况下,程序仍能够提供部分或大部分服务,这时我们就说服务的韧性很强.它是微服务中很重要的一 ...

  8. 微服务SpringCloud项目架构搭建入门

    Spring的微服务框架SpringCloud受到众多公司欢迎,给大家带来一篇框架搭建入门.本次采用的版本是Spring Cloud版本为Finchley.RELEASE. 一.SpringCloud ...

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

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

随机推荐

  1. 单片机开发——02工欲善其事必先利其器(Proteus软件安装破解)

    在单片机开发工程中,博主经常通过模拟软件Proteus进行模拟仿真,将编译生成的"HEX"文件下载在单片机芯片中,然后进行后期的debug工作,当模拟仿真完成之后,进行硬件测试部分 ...

  2. 解决jequry使用keydown无法跳转的问题

    问题描述 代码 <script> $("document").ready(function() { $("#button").click(funct ...

  3. JaveScript基础(1)之变量和数据类型

    1.JaveScript变量的定义方式: A:隐式定义:直接给变量赋值: temp='hello'; alert(temp); PS:使用变量前要先进行初始化工作,否则会报变量未被定义的错误; B:显 ...

  4. urllib使用

    1.基本方法 urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=Fals ...

  5. 【转】MySQL int转换成varchar引发的慢查询

    转自http://www.cnblogs.com/billyxp/archive/2013/05/31/3110016.html 最近一周接连处理了2个由于int向varchar转换无法使用索引,从而 ...

  6. SSM-SpringMVC-13:SpringMVC中XmlViewResolver视图解析器

     ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 还记得上篇博客提出来的问题吗? BeanNameViewResolver视图解析器每使用一道视图,就得手工配 ...

  7. MySQL事务原理&实战【官方精译】

    事务隔离级别 事务隔离是数据库处理的基础之一.隔离是I中的首字母 ACID ; 隔离级别是在多个事务同时进行更改和执行查询时,对结果的性能和可靠性,一致性和可重复性之间的平衡进行微调的设置. Inno ...

  8. javascript执行上的一点总结

    今天在为软件工程的的作业准备的时候发现代码执行上的一些问题,暴露了我的一些缺陷,先上代码 <html> <head> <script type="text/ja ...

  9. jQuery学习之旅 Item10 ajax快餐

    1. 摘要 本系列文章将带您进入jQuery的精彩世界, 其中有很多作者具体的使用经验和解决方案, 即使你会使用jQuery也能在阅读中发现些许秘籍. 本篇文章讲解如何使用jQuery方便快捷的实现A ...

  10. 关于MySQL的1064错误

    MySQL的1064错误是SQL语句写的有问题时出现的,即SQL的语法错误.笔者常常使用MySQL-python这个库来对MySQL进行操作,代码中报这个错误的一般是cursor.execute(sq ...