服务熔断
分布式系统面临的问题:
- 复杂的分布式体系结构中的应用 程序有数十个依赖关系,一个应用里面有多个功能,功能与功能之间有依赖关系,功能如果出现错误,产生等待,整条线就会卡死,服务熔断就是在这些功能中如果产生错误,避免集联故障,一个功能可以没有但是不能让他影响整条线的运行
服务雪崩
- 服务之间的相互依赖,称为“扇出”,在闪出链路上,某个微服务的调用响应时间过长或不可用,微服务调用就会占用更多的资源,引起系统崩溃,所谓雪崩效应
- 对于高流量的应用来说,单一的后端依赖可能导致所有服务器上的资源在几秒钟内饱和,这些应用程序可能导致服务之间延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发成级联故障
- 需要对故障和延迟进行隔离和管理,即使单个依赖关系失败,不能取消整个应用程序或系统
Hystrix
- 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会失败,超时,异常,Hystrix能保证几个依赖出问题的情况下,不会导致整个微服务失败,避免级联故障,提高分布式系统的弹性
- 翻译为“断路器”本身是一种开关装置,某个微服务发生故障,通过断路器的故障监控,返回一个服务的预期,处理备选的响应(FallBack),而不是长时间等待,或者抛出无法处理的异常,这样保证了服务调用方的线程不会被长时间,不必要的占用
- 服务降级、服务熔断、服务限流、接近实时的监控、、、
- SpringCloud里熔断机制通过Hystrix实现,当失败调用到一定的阀值,5秒内20次调用失败就会启动熔断机制,熔断机制注解**@HystrixCommand**
阅读文章:
- https://www.cnblogs.com/cjsblog/p/9391819.html
- 这个文章应该按照官网翻译的
- 按照期望值来讲,对于一个依赖30个服务的应用程序,每个服务有99.99%的概率的运行时间,对于一亿个请求也有300万个会失败
- 一切正常,一个月也会有2个小时服务不可用
- 正常时是这样的
- 系统产生延迟,可能阻塞整个用户请求
- 高流量情况下,一个后端依赖项的延迟可能导致所有服务器上的所有资源在数秒内饱和,无法为后续的请求提供服务
- Hystrix设计原则
- 防止任何单个依赖项耗尽所有容器
- 快速失败,而不是排队
- 提供回退,保护用户不受失败的影响
- 使用隔离技术,(隔离板、泳道、断路器模式)来限制任何一个依赖项的影响
- 实时监测,警报,优化发现时间
- 低延迟传播来优化恢复时间
- 支持对Hystrix的大多数方面的动态属性更改,允许使用低延迟反馈循环进行实时操作修改
- 避免整个依赖客户端执行中出现故障,而不仅仅是在网络流量中
- Hystrix如何实现目标
- HystrixCommand或HystrixObservableCommand(这是命令模式的一个例子)包装所有的外部系统或依赖的调用,典型的他们在一个单独的线程中执行
- 调用超时时间可自定
- 为依赖项维护一个小的线程池或信号量,线程池满了,那么依赖性会拒绝请求,而不是排队
- 调用的结果只有几种,成功,失败,超时,拒绝
- 在一段时间内满,如果服务的错误百分比超过一个阀值,会触发一个断路器来停止对特定服务的所有请求,无论是手动还是自动
- 当请求失败,被拒绝,超时或短路时,执行回退逻辑
- 近实时监控指标和配置变化
- 每个依赖项相互隔离,有各自的小线程池,和备选项
- 当延迟发生时,会被限制在资源中,并包含会退逻辑,该逻辑决定在依赖项中发生任何类型的故障时作出响应的响应
Demo
-
Hystrix创建备用方案,当服务出错时顶替上,加在provider上
-
provider添加maven依赖文本
-
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
-
给原有的请求添加备选方案
-
@RestController public class ProviderController { @Autowired ProviderTestImpl providerTest; @RequestMapping("/test") public String testMethod(){ return providerTest.test(); } @RequestMapping("/hystrix/{id}") // @HystrixCommand(fallbackMethod = "hystrixGet") public String hystrixTest(@PathVariable (value = "id") int id){ if (id==0){ throw new RuntimeException("hystrix test============"); } return "hystrix++++++++++++++++++++"+id; } public String hystrixGet(@PathVariable(value = "id") int id){ return "hystrixGet====================="+id; } }
-
当什么情况的时候抛出异常,出现异常时跳到备选方案
-
这里在执行的时候遇到过异常,找了很久,在官网的Demo中看到
-
@PathVariable(value = "id")
-
我简写了,导致报500错误
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ap23HxQ-1604889971247)(…/…/…/Library/Application Support/typora-user-images/image-20201017235355405.png)]
-
在consumer以feign的方式加个接口就行
-
测试
-
当id等于0的时候会启用备选方案
-
服务正常的时候正常使用