熔断与降价概念
什么是熔断
熔断器(CircuitBreaker),英文是CircuitBreaker,软件设计中的熔断器模式实现,思路是用一个函数调用在断路器保护对象,对故障监控。失败达到一定阈值后,断路器工作,接口调用返回一个错误,以达到保护系统,预防线程资源被大量占用,造成系统雪崩的情况
生活中的案例
生活中每家每户都在用电,小明家的电线因为故障导致了小明家停电了。而小李、小张家的电是正常使用的。电力公司没有因为小明家有故障线路而停掉其他人家的电,同时小明家没有使用有故障的电路的电。这时即为熔断。
熔断的目的是当A服务模块中的某块程序出现故障后为了不影响其他客户端的请求而做出的及时回应。
什么是降级
服务降级的处理是在客户端完成的,与服务端没有关系。
整体资源快不够用了,忍痛将某些服务先关掉,待度过难关,再回来开启。
所谓降级,就是一般是从整体符合考虑,就是当某个服务熔断之后,服务器将不再被调用,此刻客户端可以自己准备一个本地的fallback回调,返回一个缺省值,这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强。
生活中的案例
我们去银行排队办理业务,大部分的银行分为普通窗口、特殊窗口(VIP窗口,老年窗口)。某一天银行大厅排普通窗口的人巨多。这时特殊窗口贴出告示说某时刻之后再开放。那么这时特殊窗口的工作人员就可以空出来去帮其他窗口办理业务,提高办事效率,已达到解决普通窗口排队的人过的目的。这时即为降级,降级的目的是为了解决整体项目的压力,而牺牲掉某一服务模块而采取的措施。
雪崩
什么是雪崩?
微服务环境,各服务之间是经常相互依赖的,如果某个不可用,很容易引起连锁效应,造成整个系统的不可用,这种现象称为服务雪崩效应
产生原因
商品详情展示服务会依赖商品服务, 价格服务,商品评论服务,调用三个依赖服务会共享商品详情服务的线程池,如果其中的商品评论服务不可用(超时,代码异常等等), 就会出现线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩。
概括:大量请求线程同步等待造成的资源耗尽
解决方案
-
超时机制
如果我们加入超时机制,例如2s,那么超过2s就会直接返回了,那么这样就在一定程度上可以抑制消费者资源耗尽的问题
-
服务限流
通过线程池+队列的方式或者通过信号量的方式。比如商品评论比较慢,最大能同时处理10个线程,队列待处理5个,那么如果同时20个线程到达的话,其中就有5个线程被限流了,其中10个先被执行,另外5个在队列中
-
服务熔断
当依赖的服务有大量超时时,在让新的请求去访问根本没有意义,只会无畏的消耗现有资源,比如我们设置了超时时间为1s,如果短时间内有大量请求在1s内都得不到响应,就意味着这个服务出现了异常,此时就没有必要再让其他的请求去访问这个服务了,这个时候就应该使用熔断器避免资源浪费
-
服务降级
有服务熔断,必然要有服务降级。
所谓降级,就是当某个服务熔断之后,服务将不再被调用,此时客户端可以自己准备一个本地的fallback(回退)回调,返回一个缺省值。 例如:(备用接口/缓存/mock数据),这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景
Hystrix简介
hystrix对应的中文名字是“豪猪”
Hystrix 是由 Netflix 发布的针对微服务分布式系统的熔断保护中间件,是一种很好地预防服务雪崩的中间件,其实比较像电路中的保险丝,一旦某个服务不可用,导致暂用了线程资源等情况发生时,熔断器开启,不允许其它服务继续调用,导致系统雪崩。
Hystrix设计目标:
- 对来自依赖的延迟和故障进行防护和控制——这些依赖通常都是通过网络访问的
- 阻止故障的连锁反应
- 快速失败并迅速恢复
- 回退并优雅降级
- 提供近实时的监控与告警
Hystrix遵循的设计原则:
- 防止任何单独的依赖耗尽资源(线程)
- 过载立即切断并快速失败,防止排队
- 尽可能提供回退以保护用户免受故障
- 使用隔离技术(例如隔板,泳道和断路器模式)来限制任何一个依赖的影响
- 通过近实时的指标,监控和告警,确保故障被及时发现
- 通过动态修改配置属性,确保故障及时恢复
- 防止整个依赖客户端执行失败,而不仅仅是网络通信
Hystrix处理流程
Hystrix整个工作流如下:
- 构造一个 HystrixCommand或HystrixObservableCommand对象,用于封装请求,并在构造方法配置请求被执行需要的参数;
- 执行命令,Hystrix提供了4种执行命令的方法,后面详述;
- 判断是否使用缓存响应请求,若启用了缓存,且缓存可用,直接使用缓存响应请求。Hystrix支持请求缓存,但需要用户自定义启动;
- 判断熔断器是否打开,如果打开,跳到第8步;
- 判断线程池/队列/信号量是否已满,已满则跳到第8步;
- 执行HystrixObservableCommand.construct()或HystrixCommand.run(),如果执行失败或者超时,跳到第8步;否则,跳到第9步;
- 统计熔断器监控指标;
- 走Fallback备用逻辑
- 返回请求响应
从流程图上可知道,第5步线程池/队列/信号量已满时,还会执行第7步逻辑,更新熔断器统计信息,而第6步无论成功与否,都会更新熔断器统计信息。
执行命令的几种方法
Hystrix提供了4种执行命令的方法,execute()和queue() 适用于HystrixCommand对象,而observe()和toObservable()适用于HystrixObservableCommand对象。
execute()
以同步堵塞方式执行run(),只支持接收一个值对象。hystrix会从线程池中取一个线程来执行run(),并等待返回值。
queue()
以异步非阻塞方式执行run(),只支持接收一个值对象。调用queue()就直接返回一个Future对象。可通过 Future.get()拿到run()的返回结果,但Future.get()是阻塞执行的。若执行成功,Future.get()返回单个返回值。当执行失败时,如果没有重写fallback,Future.get()抛出异常。
observe()
事件注册前执行run()/construct(),支持接收多个值对象,取决于发射源。调用observe()会返回一个hot Observable,也就是说,调用observe()自动触发执行run()/construct(),无论是否存在订阅者。
如果继承的是HystrixCommand,hystrix会从线程池中取一个线程以非阻塞方式执行run();如果继承的是HystrixObservableCommand,将以调用线程阻塞执行construct()。
observe()使用方法:
- 调用observe()会返回一个Observable对象
- 调用这个Observable对象的subscribe()方法完成事件注册,从而获取结果
toObservable()
事件注册后执行run()/construct(),支持接收多个值对象,取决于发射源。调用toObservable()会返回一个cold Observable,也就是说,调用toObservable()不会立即触发执行run()/construct(),必须有订阅者订阅Observable时才会执行。
如果继承的是HystrixCommand,hystrix会从线程池中取一个线程以非阻塞方式执行run(),调用线程不必等待run();如果继承的是HystrixObservableCommand,将以调用线程堵塞执行construct(),调用线程需等待construct()执行完才能继续往下走。
toObservable()使用方法:
- 调用observe()会返回一个Observable对象
- 调用这个Observable对象的subscribe()方法完成事件注册,从而获取结果
需注意的是,HystrixCommand也支持toObservable()和observe(),但是即使将HystrixCommand转换成Observable,它也只能发射一个值对象。只有HystrixObservableCommand才支持发射多个值对象。
hystrix的简单使用
-
依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
-
在启动类中添加@EnableCircuitBreaker注解
-
在最外层添加熔断降级的处理. 在order-server中的控制器中添加@HystrixCommand(fallbackMethod = “saveFail”)注解 (注意fallbackMethod需要和原方法一样的签名)
Feign集成Hystrix
在ProductFeignApi的@FeignClient(name = “PRODUCT-SERVER”,fallback = ProductFeignHystrix.class)
配置
默认是关闭的,需要手动开启一下
feign:
hystrix:
enabled: true
超时时间调整
是否开启超时限制 (一定不要禁用)
hystrix:
command:
default:
execution:
timeout:
enabled:
超时时间调整
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 4000
断路器Dashboard监控仪表盘
步骤
-
添加dashboard和actuator依赖
-
在启动类上贴@EnableHystrixDashboard
-
在配置文件中添加开发监控地址配置
-
访问入口:http://localhost:启动端口/hystrix,然后再地址栏上输入:http://localhost:启动端口/actuator/hystrix.stream
配置
management:
endpoints:
web:
exposure:
include: "*"
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>