在使用 Hystrix组件之前呢,先了解一些概念。
1、什么是服务雪崩?何为雪崩:小雪球,越滚越大,灾难性事故!
在微服务之间进行服务调用时,由于某一个服务不可用(故障),导致其他正常的服务调用线程积压,从而引发其自身也不可用,并且还会蔓延到其他正常的服务上,最终导致所有服务不可用的现象,称为雪崩效应,即服务雪崩
。
简单来说,服务雪崩:一个服务不可用会越滚越大,最终整个系统所有服务均不可用的现象。
雪崩效应的原因是微服务之间的相互依赖。 一个服务往往涉及多个微服务的协作。这种相互依赖的情况称之为服务依赖
。
服务雪崩的解决措施就是服务熔断、服务降级。
2、什么是服务熔断?“熔断器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控或者某个异常条件被触发,直接熔断整个服务,向调用方法返回一个符合预期的、可处理的备选响应(FallBack), 而不是长时间的等待或者抛出调用方法无法处理的异常,就保证了服务调用方的线程不会被长时间占用,避免故障在分布式系统中蔓延,乃至雪崩。如果目标服务情况好转则恢复调用。
3、什么是服务降级?服务压力剧增的时候根据当前的业务情况及流量对一些服务和页面有策略的降级,以此缓解服务器的压力,以保证核心任务的进行。同时保证部分甚至大部分任务客户能得到正确的相应。也就是当前的请求处理不了了或者出错了,给一个默认的返回。
降级服务也有不同的层级。比如,电商网站在双十一抢购时,可以不展示广告等,仅展示重要信息。
简单来说,服务降级:为保证系统核心服务的正常运行,选择关闭系统一些中边缘服务(直接返回拖底数据,即响应一下静态反馈数据),来防止防止系统的整体缓慢甚至崩溃的一种技术手段。
4、服务熔断与服务降级的区别区别在于熔断是对调用链路的保护,而降级是对系统过载的一种保护处理。 相同点
- 目的很一致 都是从可用性可靠性着想,为防止系统的整体缓慢甚至崩溃。最终让用户体验到的是某些功能暂时不可达或不可用。
不同点
-
出发的原因不同 服务熔断一般是某个服务(多指当前调用下的服务提供者)故障引起,一般都是服务基于策略的自动触发。 服务降级一般是从整体负荷考虑(cpu、内存等)完全靠人手动升降级服务显然不可能。
-
管理目标的层次不太一样 熔断其实是一个框架级的处理,每个微服务都需要(无层级之分)。 降级一般需要对业务有层级之分。
Hystrix(/hɪst'rɪks/)
翻译过来是 豪猪的意思。
Hystrix 是 Netflix 针对微服务分布式系统采用的熔断保护组件,相当于电路中的保险丝。断路器使得微服系统可以在一些糟糕的情况下,仍然尽量保证系统的可用性。
在分布式系统中,许多服务依赖不可避免的会调用失败,超时、异常等,Hystrix能够保证在一个服务依赖出问题的情况下,不会导致整体服务失败,避免级联故障(服务雪崩现象),提高分布式系统的弹性。
在微服务架构下,很多服务都相互依赖,如果不能对依赖的服务进行隔离,那么服务本身也有可能发生故障,Hystrix 通过 HystrixCommand 对调用进行隔离,这样可以阻止故障的连锁效应,能够让接口调用快速失败并迅速恢复正常,或者回退并优雅降级。
2、Hystrix解决服务雪崩问题的手段解决服务雪崩问题主要是服务降级,主要包括:
- 线程隔离: 用户请求不直接访问服务,而是使用线程池的线程访问服务。加速了服务调用失败的判断时间
- 服务降级: 及时返回服务调用失败的结果,让线程不会因为等待服务而阻塞。
触发 Hystrix服务降级的情况有:
- 线程池已满
- 请求超时
- 1、包裹请求: Hystrix 会把服务的请求封装成一个 HystrixCommand对象,它包裹对依赖的调用逻辑,每个命令在独立的线程中执行,使用了设计模式中的“命令模式”;
- 2、跳闸机制: 当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间;
- 3、资源隔离: Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程已满,则发向该依赖的请求就会被立即拒绝,而不是排队等候,从而加速失败判定;
- 4、监控: Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝的请求等;
- 5、回退机制: 当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑,回退逻辑由开发人员自行提供,如返回一个缺省值;
- 6、自我修复: 断路器打开一段时间后,会自动进入“半开”状态,此时断路器可允许一个请求访问依赖的服务,若请求成功,则断路器关闭,否则断路器转为“打开”状态;
在服务熔断中,使用的熔断器,也叫断路器,其英文单词为:Circuit Breaker
。
Hystrix的服务熔断机制,可以实现弹性容错;当服务请求情况好转之后,可以自动重连。通过断路的方式,将后续请求直接拒绝,一段时间(默认5秒)之后允许部分请求通过,如果调用成功则回到断路器关闭状态,否则继续打开,拒绝请求的服务。
状态机有3个状态:
- Closed:关闭状态(断路器关闭) 所有请求都正常访问。
- Open:打开状态(断路器打开) 所有请求都会被降级。Hystrix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
- Half Open:半开状态,不是永久的 断路器打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放部分请求通过,若这些请求都是健康的,则会关闭断路器,否则继续保持打开,再次进行休眠计时
搭建项目,传送门:Eureke服务治理中心
1、引入依赖在服务调用方引入依赖,这里User服务调用Order服务。
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
2、注解开启
调用方启动类使用 @EnableCircuitBreaker注解
,表示开启 Hystrix断路器。 也可以使用 @SpringCloudApplication注解
,是它们三个的组合。
//@SpringBootApplication
//@EnableEurekaClient
//@EnableCircuitBreaker // 表示开启 Hystrix断路器
@SpringCloudApplication
public class UserApplication {
// 负载均衡
@LoadBalanced
@Bean
public RestTemplate initRestTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
3、在controller上或者方法上添加注解
(1)在单个方法上
在需要使用熔断调用函数的方法上使用 @HystrixCommand 注解
并指定 fallbackMethod 属性,定义熔断后的调用函数。
注意:
方法和熔断函数的参数要保持一致,返回值类型必须相同。
(2)在 controller上
使用 @DefaultProperties注解 当需要熔断的函数过多的使用,在使用单个的熔断,就过于繁琐,每一个方法都需要一个熔断,所以可以在类上使用全局的熔断。
使用注解
@DefaultProperties
:使用在类上,声明全局的熔断函数@HystrixCommand
:使用在方法上,默认使用全局的熔断 ,也可以通过fallbackMethod 属性指明自己的熔断函数
注意:
在全局的熔断函数不需要参数,返回String。
@RestController
@RequestMapping("/hystrix")
@DefaultProperties(defaultFallback = "fallbackMethod")
public class User2Controller {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/get1/{id}")
@HystrixCommand
public String get1(@PathVariable Long id) {
String url = "http://ORDER/order/get1/" + id;
String res = restTemplate.getForObject(url, String.class);
return res;
}
public String fallbackMethod(){
return "网络开小差了,请稍后再试!";
}
@PostMapping("/post1")
@HystrixCommand(fallbackMethod = "post1fallback")
public ResponseEntity post1(@RequestBody OrderDO orderDO) {
String url = "http://ORDER/order/post1";
OrderDO res = restTemplate.postForObject(url, orderDO, OrderDO.class);
return ResponseEntity.ok(res).;
}
public ResponseEntity post1fallback(OrderDO orderDO){
System.out.println("添加失败,服务正忙,请稍后再试!");
return ResponseEntity.ok(new OrderDO());
}
}
两种方式就写一起测试了,单个方法上,返回值类型简单处理了。Order服务不需要改动,测试时,将Order服务做重启,下线等模拟故障,访问 User服务就会看到如下信息。进去了熔断处理,而不会像之前系统报错。
4、修改 Hystrix默认的超时时间
当User服务调用Order服务资源时 Hystrix得默认超时时间是1s。可以在调用方的配置文件中修改。
hystrix:
command:
default:
execution:
isolation:
thread:
# 设置hystrix超时时间(单位毫秒),默认1000ms
timeoutInMilliseconds: 3000
circuitBreaker:
errorThresholdPercentage: 50 # 触发熔断错误比例阈值,默认值50%
sleepWindowInMilliseconds: 5000 # 熔断后休眠时长,默认值5秒
requestVolumeThreshold: 20 # 熔断触发最小请求次数,默认值是20
参考文章:
- SpringCloud-容错处理Hystrix熔断器(五)
—— Stay Hungry. Stay Foolish. 求知若饥,虚心若愚。