通俗易懂的SpringCloud(三)熔断器
文章目录
- 三、断路器-Hystrix
- 3.1、相关概念
- 3.1.1、服务雪崩
- 2.1.2、服务熔断
- 2.1.3、服务降级
- 2.1.4、降级和熔断的总结
- 3.2、服务降级
- 3.3、使用OpenFeign处理服务降级
三、断路器-Hystrix
在分布式环境中,许多服务依赖项不可避免地会失败。Hystrix是一个库,它通过添加延迟容忍和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止它们之间的级联故障以及提供后备选项来实现这一点,所有这些都可以提高系统的整体弹性。
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统中,许多依赖不可避免的会调用失败,超时、异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩现象),提高分布式系统的弹性。
3.1、相关概念
3.1.1、服务雪崩
在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程
如果下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
# 引起雪崩的原因:1、硬件故障;2、程序Bug;3、缓存击穿(用户大量访问缓存中没有的键值,导致大量请求查询数据库,使数据库压力过大);4、用户大量请求;
# 三个阶段第一阶段: 服务不可用;第二阶段:调用端重试加大流量(用户重试/代码逻辑重试)第三阶段:服务调用者不可用(同步等待造成的资源耗尽)
# 解决方案(1)、应用扩容(扩大服务器承受力)(2)、流量控制(超出限定流量,返回类似重试页面让用户稍后再试)(3)、缓存:将用户可能访问的数据大量的放入缓存中,减少访问数据库的请求(4)、服务降级服务接口拒绝服务页面拒绝服务延迟持久化随机拒绝服务(5)、服务熔断
2.1.2、服务熔断
“熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控,某个异常条件被触发,直接熔断整个服务。向调用方法返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。服务熔断是解决服务雪崩的重要手段。
2.1.3、服务降级
服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此环节服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的相应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。
2.1.4、降级和熔断的总结
# 1.共同点
- 目的很一致,都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃,采用的技术手段;
- 最终表现类似,对于两者来说,最终让用户体验到的是某些功能暂时不可达或不可用;
- 粒度一般都是服务级别,当然,业界也有不少更细粒度的做法,比如做到数据持久层(允许查询,不允许增删改);
- 自治性要求很高,熔断模式一般都是服务基于策略的自动触发,降级虽说可人工干预,但在微服务架构下,完全靠人显然不可能,开关预置、配置中心都是必要手段;# 2.异同点
- 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
- 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)# 3.总结
- 熔断必会触发降级,所以熔断也是降级一种,区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理
3.2、服务降级
当较低级别的服务中的服务故障可能会导致级联故障,直至用户。甚至出现雪崩现象,如果使用了Hystrix则可触发熔断来防止级联故障,那么断路器的触发条件是什么呢?
A service failure in the lower level of services can cause cascading failure all the way up to the user. When calls to a particular service exceed circuitBreaker.requestVolumeThreshold
(default: 20 requests) and the failure percentage is greater than circuitBreaker.errorThresholdPercentage
(default: >50%) in a rolling window defined by metrics.rollingStats.timeInMilliseconds
(default: 10 seconds), the circuit opens and the call is not made. In cases of error and an open circuit, a fallback can be provided by the developer.(摘自springcloud hystrix官网 https://cloud.spring.io/spring-cloud-netflix/2.2.x/reference/html/#hystrix-metrics-stream)
译文:较低级别的服务中的服务故障可能会导致级联故障,直至用户。当在由(默认值:10秒)定义的滚动窗口中,对特定服务的调用超过circuitBreaker.requestVolumeThreshold
(默认值:20个请求)并且失败百分比大于circuitBreaker.errorThresholdPercentage
(默认值:> 50%)时metrics.rollingStats.timeInMilliseconds
,电路将断开并且不会进行调用。在错误和断路的情况下,开发人员可以提供后备功能。
# 总结 断路器的触发条件1、当满足一定的阀值的时候(默认10秒内超过20个请求次数)2、 当失败率达到一定的时候(默认10秒内超过50%的请求失败)3、 到达以上阀值,断路器将会开启4、 当断路器开启的时候,所有请求都不会进行转发5、 一段时间之后(默认是5秒),这个时候断路器是半开状态,会让其中一个请求进行转发。如果成功,断路器会关闭,若失败,继续开启。重复4和5。
在清楚断路器的触发条件的时候我们来模拟服务熔断,并使用hystrix来进行处理
引入hystrix依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
为了方便演示,新建两个项目。订单服务对外暴露的接口如下。在商品服务中新增方法,这里选择抛出异常的方式来触发服务熔断。
package com.laodai.controller;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.HashMap; import java.util.Map;/*** @作者 老代* @微信 laodai6_6* @时间 2021/3/12 12:41* @Version 1.0*/ @RestController public class CommodityController {/*** 通过抛出异常的方式来触发服务不可用*/@GetMapping("/commodity/getInfoById")public Map<String,Object> getInfoById(Integer id){if (id < 0){throw new RuntimeException("非法id【"+id+"】,服务不可用");}else {Map<String,Object> map = new HashMap<>();map.put("status",200);map.put("msg","查询成功,返回id为:"+id+"】的商品信息");return map;}} }
package com.laodai.controller;import com.laodai.service.CommodityService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.Map;/*** @作者 老代* @微信 laodai6_6* @时间 2021/3/12 13:02* @Version 1.0*/ @RestController public class OrderController {@Autowiredprivate CommodityService commodityService;@GetMapping("/order/fuse")public Map<String,Object> fuse(Integer id){return commodityService.getInfoById(id);}}
使用注解来开启熔断,并指定熔断后的降级方法
package com.laodai.controller;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;import java.util.HashMap; import java.util.Map;/*** @作者 老代* @微信 laodai6_6* @时间 2021/3/12 12:41* @Version 1.0*/ @RestController public class CommodityController {/*** 通过抛出异常的方式来触发服务不可用*/@GetMapping("/commodity/getInfoById")@HystrixCommand(fallbackMethod = "fuseFallBack")public Map<String,Object> getInfoById(Integer id){if (id < 0){throw new RuntimeException("非法id【"+id+"】,服务不可用");}else {Map<String,Object> map = new HashMap<>();map.put("status",200);map.put("msg","查询成功,返回id为:"+id+"】的商品信息");return map;}}//降级函数,当服务熔断时会调用此方法public Map<String,Object> fuseFallBack(Integer id){Map<String,Object> map = new HashMap<>();map.put("status",500);map.put("msg","【"+id+"】非法id,请检查后重新输入");return map;} }
测试验证
这里为了触发Hystrix的熔断机制,即10秒内超过20个请求都失败,这里使用了apache JMeter压力测试工具
这里直接在1s中发送了100次错误请求。
5.存在问题
我们可以看到,如果为每一个服务方法开发一个降级,对于我们来说,`可能会出现大量的代码的冗余,不利于维护,这个时候就需要加入默认服务降级处理方法`
6、改进程序
package com.laodai.controller;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;
import java.util.Map;/*** @作者 老代* @微信 laodai6_6* @时间 2021/3/12 12:41* @Version 1.0*/
@RestController
public class CommodityController {/*** 通过抛出异常的方式来触发服务不可用*/@GetMapping("/commodity/getInfoById")@HystrixCommand(fallbackMethod = "fuseFallBack")
// @HystrixCommand(defaultFallback = "defaultFallBack")public Map<String,Object> getInfoById(Integer id){if (id < 0){throw new RuntimeException("非法id【"+id+"】,服务不可用");}else {Map<String,Object> map = new HashMap<>();map.put("status",200);map.put("msg","查询成功,返回id为:"+id+"】的商品信息");return map;}}//降级函数,当服务熔断时会调用此方法public Map<String,Object> fuseFallBack(Integer id){Map<String,Object> map = new HashMap<>();map.put("status",500);map.put("msg","【"+id+"】非法id,请检查后重新输入");return map;}public Map<String,Object> defaultFallBack(){Map<String,Object> map = new HashMap<>();map.put("status",500);map.put("msg","未知异常,请稍后重试");return map;}
}
3.3、使用OpenFeign处理服务降级
通过我们上面的例子我们虽然实现了服务的降级,但是问题就是
业务代码和公共代码耦合在一起了
,这对后续的阔这和维护增加了困难,因此我们需要另外的将降级逻辑提取出来。我们上篇文章介绍的OpenFeign其实就已经集成了Hystrix(如下图),我们可以直接使用OpenFeign来实现服务的降级。
在订单服务的属性配置文件中开启OpenFeign支持hystrix(默认为关闭)
#开启feign对hystrix的支持 feign.hystrix.enabled=true
新增降级服务类,实现CommodityService接口。因为我们要对OpenFeign接口进行服务降级,所以我们需要新增一个回调类实现CommodityService接口,对每个方法进行回调处理。记得声明为组件@Component
package com.laodai.service;import org.springframework.stereotype.Component;import java.util.HashMap; import java.util.Map;/*** @作者 老代* @微信 laodai6_6* @时间 2021/3/12 19:56* @Version 1.0*/ @Component public class CommodityServiceImpl implements CommodityService{@Overridepublic Map<String, Object> getInfoById(Integer id) {Map<String,Object> map = new HashMap<>();map.put("status",500);map.put("msg","这里是客户端降级处理提醒:服务异常,请稍后重试");return map;} }
在接口服务类CommodityService通过指定@FeignClient的fallback属性来指定具体的降级处理类
package com.laodai.service;import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam;import java.util.Map;/*** @作者 老代* @微信 laodai6_6* @时间 2021/3/12 13:01* @Version 1.0*/ @FeignClient(name="commodity",fallback = CommodityServiceImpl.class) public interface CommodityService {@GetMapping("/commodity/getInfoById")Map<String,Object> getInfoById(@RequestParam("id") Integer id); }
测试验证
总结
# 注意:1、使用Feign+Hystrix的方式处理降级为客户端方案,也就是服务消费者方案2、如果服务端降级和客户端降级同时开启,要求服务端降级方法的返回值必须与客户端方法降级的返回值一致
Hystrix还有一个Hystrix Dashboard,可以用来观察熔断的详细信息。但是在spirngcloud新版本中配置起来十分复杂,所以这里就不在赘述了。如果想开启此功能的小伙伴请自行百度。
另外还想说的是Hystrix也停止维护了!!!无语
通俗易懂的SpringCloud(三)熔断器相关推荐
- SpringCloud Hystrix熔断器
SpringCloud Hystrix熔断器 15.Hystrix熔断器:简介及作用 目标:理解Hystrix的作用 介绍:Hystrix,英文意思是豪猪,全身是刺,看起来就不好惹,是一种保护机制. ...
- SpringCloud(三):监控中心 hystrix turbine
SpringCloud(三):监控中心 hystrix turbine 1.介绍 Hystrix-dashboard是一款针对Hystrix进行实时监控的工具,通过Hystrix Dashboard我 ...
- SpringCloud 组件 熔断器Hystrix
Hystrix 的中文名字是"豪猪",豪猪是满身长满了刺,能够保护自己不受天敌的伤害,代表了一种防御机制,Hystrix 在 SpringCloud 中负责服务熔断和服务降级的作用 ...
- SpringCloud(三) Eureka之服务注册发现以及实现工程间调用
概述:本章节将介绍Eureka客户端如何与EurekaServer端链接,以及生产者工程如何将服务注册到Eureka注册中心中去,消费者工程怎么从EurekaServer端获取生产者工程的服务地址,并 ...
- SpringCloud(三) Eureka注册中心介绍以及单机版搭建
一.Eureka 介绍 Spring Cloud Eureka 是 Spring Cloud Netfix微服务套件中的一部分,它基于 Netfix Eureka 做了二次封装,主要负责完成微服务架构 ...
- 试着让动态代理变得通俗易懂,通过三个案例
动态代理 什么是代理? 代理思想就是被代理者没有能力,或者不愿意去完成某件事情,需要找个人(代理)代替自己去完成这件事. 别想的太复杂,就是找一个黄牛.举个最近的例子,周杰伦要开演唱会了,大家需要在大 ...
- springcloud(三):服务提供与调用
上一篇文章我们介绍了eureka服务注册中心的搭建,这篇文章介绍一下如何使用eureka服务注册中心,搭建一个简单的服务端注册服务,客户端去调用服务使用的案例. 案例中有三个角色:服务注册中心.服务提 ...
- Spring Cloud(三) 熔断器Hystrix
前文回顾: Spring Cloud(一)Eureka Server-单体及集群搭建 Spring Cloud(二) 配置Eureka Client 一.Hystrix介绍 在微服务架构中通常会有多个 ...
- SpringCloud(三)Eureka之集群搭建以及将服务注册到多个EurekaServer
概述:为了保证EurekaServer的高可用,可以采用服务集群方式.当有一台挂掉时,其他节点仍可以继续提供服务.在EurekaServer的集群配置中,他们为分别配置对方为自己的注册中心,并将自己节 ...
最新文章
- (二)spring cloud微服务分布式云架构-整合企业架构的技术点
- 中如何使用echart_jQueryEasyUI中的拖拽事件如何使用
- vue怎么vw布局好用_vue cli3项目的pc自适应布局_vw
- vue数组修改不触发视图更新、vue向响应式对象添加或删除属性
- c++ winpcap开发(4)
- UNIX 环境高级编程(六)—— 程序和进程
- 自定义函数hello,并注册到hive源码中并重新编译
- Exadata:Smart Scan(二) FAST FULL SCAN
- [解疑][TI]TI毫米波雷达系列(五):恒虚警算法(CFAR)原理
- python相关性分析函数_python实现相关性分析
- 警惕!黑客通过iPhone充电线劫持您的计算机
- 在Linux中安装mysql后遇到错误20008解决方案
- 算法-时间频度 时间复杂度 空间复杂度
- TFN F7 M1 光时域反射仪 多模OTDR 光纤测试仪 高精度 触摸屏 波长850/1300nm
- ubuntu 通过文件夹打开终端,通过终端打开文件夹
- 什么?你项目还在用Date表示时间?
- 两部苹果手机同步照片_苹果手机如何恢复照片?最近删除清空也不用怕!
- element---组件--form
- 03Fiddler APP 抓包
- 关于多硬盘电脑系统盘中没有EFI分区的解决方法