前言
在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与发现的方式互相依赖。

由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,

而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,

进一步甚至出现故障的蔓延最终导致整个系统的瘫痪。如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定。

为了解决这样的问题,因此产生了断路器等一系列的服务保护机制。

为了使得故障隔离,Hystrix提供的解决方案我们需要关注一下几个部分:

  • 舱壁隔离(线程隔离)
  • 超时控制,服务降级
  • 熔断机制

1.仓壁隔离

“舱壁模式”对于熟悉Docker的读者一定不陌生,Docker通过“舱壁模式”实现进程的隔离,使得容器与容器之间不会互相影响。

而Hystrix则使用该模式实现线程池的隔离,它会为每一个Hystrix命令创建一个独立的线程池,这样就算某个在Hystrix命令包装下的依赖服务出现延迟过高的情况,也只是对该依赖服务的调用产生影响,而不会拖慢其他的服务。

如何使用?

我们使用@HystrixCommand来将某个函数包装成了Hystrix命令,Hystrix框架就会自动的为这个函数实现调用的隔离。

Spring Cloud构建微服务架构:服务容错保护(Hystrix依赖隔离)

2.超时控制和服务降级

如果服务提供方延迟了自己设置的超时限制,而服务消费方触发了服务请求超时异常,服务消费者就通过HystrixCommand注解中指定的降级逻辑进行执行,

因此该请求的结果返回了fallback。这样的机制,对自身服务起到了基础的保护,同时还为异常情况提供了自动的服务降级切换机制。

Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)

@Repository
@DefaultProperties(groupKey="userDao",
//命令执行超时时间,默认1000ms
commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="")},
threadPoolProperties={@HystrixProperty(name="coreSize",value="")
,@HystrixProperty(name="maxQueueSize",value="")},
threadPoolKey="userDao"
)
public class UserDao{ public User getUserByTokenFb(String token){
return new User();
} /**
* 调用鉴权服务
* @param token
* @return
*/
@HystrixCommand(fallbackMethod="getUserByTokenFb")
public User getUserByToken(String token) {
String url = "http://" + userServiceName + "/user/get?token=" + token;
ResponseEntity<RestResponse<User>> responseEntity = rest.get(url, new ParameterizedTypeReference<RestResponse<User>>() {});
RestResponse<User> response = responseEntity.getBody();
if (response == null || response.getCode() != ) {
return null;
}
return response.getResult();
}
}

3.熔断机制

“断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。

在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),直接切断原来的主逻辑调用。

那么当断路器打开之后会发生什么呢?我们先来说说断路器未打开之前,对于之前那个示例的情况就是每个请求都会在当hystrix超时之后返回fallback,每个请求时间延迟就是近似hystrix的超时时间,

如果设置为5秒,那么每个请求就都要延迟5秒才会返回。当熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,这个时候熔断器打开。

打开之后,再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,这个时候就不会等待5秒之后才返回fallback。

通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。

熔断器的开关能保证服务调用者在调用异常服务时, 快速返回结果, 避免大量的同步等待. 并且熔断器能在一段时间后继续侦测请求执行结果, 提供恢复服务调用的可能.

熔断器模式有三种状态:

关闭、打开、半开

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

  1. 当熔断器开关关闭时, 请求被允许通过熔断器. 如果当前健康状况高于设定阈值, 开关继续保持关闭. 如果当前健康状况低于设定阈值, 开关则切换为打开状态.

  2. 当熔断器开关打开时, 请求被禁止通过.

  3. 当熔断器开关处于打开状态, 经过一段时间后, 熔断器会自动进入半开状态, 这时熔断器只允许一个请求通过. 当该请求调用成功时, 熔断器恢复到关闭状态. 若该请求失败, 熔断器继续保持打开状态, 接下来的请求被禁止通过.

Hystrix使用命令模式

Hystrix使用命令模式(继承HystrixCommand类)来包裹具体的服务调用逻辑(run方法), 并在命令模式中添加了服务调用失败后的降级逻辑(getFallback).
同时我们设置当前服务线程池和熔断器的相关参数.

附上一张终极原理图:

  1. 构建Hystrix的Command对象, 调用执行方法.

  2. Hystrix检查当前服务的熔断器开关是否开启, 若开启, 则执行降级服务getFallback方法.

  3. 若熔断器开关关闭, 则Hystrix检查当前服务的线程池是否能接收新的请求, 若超过线程池已满, 则执行降级服务getFallback方法.

  4. 若线程池接受请求, 则Hystrix开始执行服务调用具体逻辑run方法.

  5. 若服务执行失败, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.

  6. 若服务执行超时, 则执行降级服务getFallback方法, 并将执行结果上报Metrics更新服务健康状况.

  7. 若服务执行成功, 返回正常结果.

  8. 若服务降级方法getFallback执行成功, 则返回降级结果.

  9. 若服务降级方法getFallback执行失败, 则抛出异常.

Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)

注:一些配置

要使用hystrix需要在pom文件中添加下面两个依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.0..RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4..RELEASE</version>
</dependency>

服务消费者application.properties

#命令执行超时时间,默认1000ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=
hystrix.threadpool.default.coreSize=
hystrix.threadpool.default.maxQueueSize= #错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50
hystrix.command.default.circuitBreaker.errorThresholdPercentage=
#休眠时间窗
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=
#必须要配置这个暴露监控端口,这样才能hystrix dashboard查看监控信息
management.endpoints.web.exposure.include=*

这是做的全局默认配置,如果在某个服务级别上单独配置,使用@DefaultProperties在类级别上做配置:

@DefaultProperties(groupKey="userDao",
//命令执行超时时间,默认1000ms
commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="")},
threadPoolProperties={@HystrixProperty(name="coreSize",value="")
,@HystrixProperty(name="maxQueueSize",value="")},
threadPoolKey="userDao"
)

另外后还需要加注解@HystrixCommand做方法级别的命令控制,默认使用类级别的参数。

参考:

防雪崩利器:熔断器 Hystrix 的原理与使用

对于监控的状态信息可以通过Hystrix提供的dashboard来直观显示,可安装这篇文章进行操作

Spring Cloud中Hystrix仪表盘与Turbine集群监控

微服务—熔断器Hystrix的更多相关文章

  1. 微服务-熔断器 Hystrix 的原理与使用

    前言 分布式系统中经常会出现某个基础服务不可用造成整个系统不可用的情况, 这种现象被称为服务雪崩效应. 为了应对服务雪崩, 一种常见的做法是手动服务降级. 而Hystrix的出现,给我们提供了另一种选 ...

  2. 【一起学源码-微服务】Hystrix 源码一:Hystrix基础原理与Demo搭建

    说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一个系列文章讲解了Feign的源码,主要是Feign动态 ...

  3. 【一起学源码-微服务】Hystrix 源码三:Hystrix核心流程:Hystix降级、熔断等原理剖析

    说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一讲我们讲解了Hystrix在配合feign的过程中,一 ...

  4. 【一起学源码-微服务】Hystrix 源码二:Hystrix核心流程:Hystix非降级逻辑流程梳理

    说明 原创不易,如若转载 请标明来源! 欢迎关注本人微信公众号:壹枝花算不算浪漫 更多内容也可查看本人博客:一枝花算不算浪漫 前言 前情回顾 上一讲我们讲了配置了feign.hystrix.enabl ...

  5. spring cloud微服务快速教程之(四)熔断器(Hystrix)及其工具(Dashboard、Turbine)

    0-为什么需要熔断器 在分布式系统中,各个服务相互调用相互依赖,如果某个服务挂了,很可能导致其他调用它的一连串服务也挂掉或者在不断等待中耗尽服务器资源,这种现象称之为雪崩效应: 未来防止系统雪崩,熔断 ...

  6. java框架之SpringCloud(1)-微服务及SpringCloud介绍

    微服务概述 是什么 业界大牛 Martin Fowler 这样描述微服务: 参考[微服务(Microservices)-微服务原作者Martin Flower博客翻译]. 下面是关于上述博客中的部分重 ...

  7. Java面试——微服务

    1.什么是微服务?    就目前而言,对于微服务业界并没有一个统一的,标准的定义. 但通常而言,微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分一组小的服务,每个服务运行在其独立 ...

  8. SpringCloud微服务(04):Turbine组件,实现微服务集群监控

    本文源码:GitHub·点这里 || GitEE·点这里 写在前面,阅读本文前,你需要了解熔断器相关内容 SpringCloud微服务:Hystrix组件,实现服务熔断 一.聚合监控简介 1.Dash ...

  9. SpringCloud学习系列-微服务

    最近和尚硅谷周阳老师学习了Spring Cloud感觉有必要在这里做下笔记和总结. 软件系统架构演变 单一应用架构当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用 ...

随机推荐

  1. Myeclipse中设置jsp页面的默认编码格式

    在MyEclispe中创建Jsp页面,Jsp页面的默认编码是“ISO-8859-1”,如下图所示: 在这种编码下编写中文是没有办法保存Jsp页面的,会出现如下的错误提示: 因此可以设置Jsp默认的编码 ...

  2. iframe在移动端的缩放

    工作中碰到个奇怪的问题,折腾了大半天,终于算是解决了,这里把分析思路和解决办法记录下. 项目是做响应式的公司官网,前期的静态图页面切完后就提交给后台作为模板使用了,我也就基本退出项目. 在后端落地时发 ...

  3. 利用localStorage事件来跨标签页共享sessionStorage

    //干货 利用localStorage事件来跨标签页共享sessionStorage //因为cookie保存字节数量有限,很多童鞋考虑用html5 storage来保存临时数据,Sessionsto ...

  4. CSS 伪类(下)结构性伪类\UI伪类\动态伪类和其他伪类 valid check enable child required link visit

      伪类选择器汇总伪类选择器有4种, 结构性伪类\UI伪类\动态伪类和其他伪类. 具体如下 结构性伪类选择器结构性伪类选择器它能够根据元素在文档中的位置选择元素, 这类元素都有个前缀":&q ...

  5. asp.net修改上传文件大小

    我们大家都知道ASP.NET为我们提供了文件上传服务器控件FileUpload,默认情况下可上传的最大文件为4M,如果要改变可上传文件大小限制,那么我们可以在web.config中的httpRunti ...

  6. 交叉编译 Cross-compiling for Linux

    @(134 - Linux) Part 1 交叉编译简介 1.1 What is cross-compiling? 对于没有做过嵌入式编程的人,可能不太理解交叉编译的概念,那么什么是交叉编译?它有什么 ...

  7. try catch 一点小记录

    这两天做了新的需求,做完之后 在测试环境下 完美通关.之后部署到了预发布环境,然而怎么尝试都不通过.刚开始看到 预发布的一个配置文件错了.发邮件改了下,但是依然流程跑不通.之后 一步步在测试环境看代码 ...

  8. ubuntu16 下安装redis 以及设置其为开机启动

    1.下载redis安装包 sudo wget http://download.redis.io/releases/redis-3.2.6.tar.gz 2.解压 tar -zxvf  redis-3. ...

  9. 8.Bootstrap CSS编码规范

    Bootstrap CSS编码规范 本节的介绍内容为 Bootstrap 中的 CSS 编码规范. 语法 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得一致展现的方法. 为选择 ...

  10. 为什么说对象字面量赋值比new Object()高效?

    http://www.cnblogs.com/mushishi/p/5811743.html