前言
在微服务架构中,我们将系统拆分成了一个个的服务单元,各单元应用间通过服务注册与发现的方式互相依赖。
由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问题出现调用故障或延迟,
而这些问题会直接导致调用方的对外服务也出现延迟,若此时调用方的请求不断增加,最后就会出现因等待出现故障的依赖方响应而形成任务积压,线程资源无法释放,最终导致自身服务的瘫痪,
进一步甚至出现故障的蔓延最终导致整个系统的瘫痪。如果这样的架构存在如此严重的隐患,那么相较传统架构就更加的不稳定。
为了解决这样的问题,因此产生了断路器等一系列的服务保护机制。
为了使得故障隔离,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="5000")}, threadPoolProperties={@HystrixProperty(name="coreSize",value="10") ,@HystrixProperty(name="maxQueueSize",value="1000")}, 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() != 0) { return null; } return response.getResult(); } }
3.熔断机制
“断路器”本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,“断路器”能够及时的切断故障电路,防止发生过载、发热、甚至起火等严重后果。
在分布式架构中,断路器模式的作用也是类似的,当某个服务单元发生故障(类似用电器发生短路)之后,通过断路器的故障监控(类似熔断保险丝),直接切断原来的主逻辑调用。
那么当断路器打开之后会发生什么呢?我们先来说说断路器未打开之前,对于之前那个示例的情况就是每个请求都会在当hystrix超时之后返回fallback
,每个请求时间延迟就是近似hystrix的超时时间,
如果设置为5秒,那么每个请求就都要延迟5秒才会返回。当熔断器在10秒内发现请求总数超过20,并且错误百分比超过50%,这个时候熔断器打开。
打开之后,再有请求调用的时候,将不会调用主逻辑,而是直接调用降级逻辑,这个时候就不会等待5秒之后才返回fallback。
通过断路器,实现了自动地发现错误并将降级逻辑切换为主逻辑,减少响应延迟的效果。
附上一张终极原理图:
Spring Cloud构建微服务架构:服务容错保护(Hystrix断路器)
注:一些配置
要使用hystrix需要在pom文件中添加下面两个依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> <version>1.4.4.RELEASE</version> </dependency>
服务消费者application.properties
#命令执行超时时间,默认1000ms hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000 hystrix.threadpool.default.coreSize=5 hystrix.threadpool.default.maxQueueSize=1 #错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50 hystrix.command.default.circuitBreaker.errorThresholdPercentage=10 #休眠时间窗 hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=100000 #必须要配置这个暴露监控端口,这样才能hystrix dashboard查看监控信息 management.endpoints.web.exposure.include=*
这是做的全局默认配置,如果在某个服务级别上单独配置,使用@DefaultProperties在类级别上做配置:
@DefaultProperties(groupKey="userDao", //命令执行超时时间,默认1000ms commandProperties={@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")}, threadPoolProperties={@HystrixProperty(name="coreSize",value="10") ,@HystrixProperty(name="maxQueueSize",value="1000")}, threadPoolKey="userDao" )
另外后还需要加注解@HystrixCommand做方法级别的命令控制,默认使用类级别的参数。
另外这是一篇经典好文,对于理解熔断器的机制非常有帮助!
防雪崩利器:熔断器 Hystrix 的原理与使用
对于监控的状态信息可以通过Hystrix提供的dashboard来直观显示,可安装这篇文章进行操作
Spring Cloud中Hystrix仪表盘与Turbine集群监控
原文地址:https://www.cnblogs.com/xiangkejin/p/9026188.html