9.1 什么是 Hystrix
Hystrix 是 一个 用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
“断路器/熔断器” 本身是一种 开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似 熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证服务调用方的线程不会被长时间,不必要的占用! 从而避免了故障在分布式系统中的蔓延,乃至 雪崩
。
Hystrix 能干嘛
- 服务降级
- 服务熔断
- 服务限流
- 接近实时的监控
- ……
9.2 什么是 服务熔断
熔断机制是针对于雪崩效应提出的一种微服务链路保护机制。
当 扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回 错误的响应信息。 当监测到 该节点 微服务调用 响应正常后 恢复 调用 链路。在 SpringCloud 框架里熔断机制通过 Hystrix 实现。Hystrix 会 监控微服务间调用的状况,当 失败的调用 到 一定阈值,缺省是 5 秒 内 20 次 调用失败 就会 启动 熔断机制。 熔断机制的 注解是 @HystrixCommand
9.3 尝试 服务熔断机制
- 新建一个
springcloud-provider-dept-hystrix-8001
来测试 hystrix 的 服务熔断。
2. 导入 Hystrix 依赖
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
3. 我们正常来说,如果 服务请求/方法 出现了异常,肯定要 抛出 这个异常!比如说这样做!id 如果 传递 过来的是 一个压根就找不到的 id,那么 肯定 不对劲,所以要抛出异常。
package top.muquanyu.springcloud.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import top.muquanyu.springcloud.pojo.Dept;
import top.muquanyu.springcloud.service.DeptServiceImpl;
import java.util.List;
// 提供 RestFul 服务的 就只能是 Controller 接口
@RestController
public class DeptController {
@Autowired
private DeptServiceImpl deptService;
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
// 这个方法 其实 是有问题的,如果 id 传过来的 是找不到的呢。。是没有的呢?
// 那么 我们 是不是 就查不到了?
Dept dept = deptService.queryByID(id);
if(dept == null){
throw new RuntimeException("id => "+ id + " 不存在该 Dept 对象");
}
return dept;
}
- 使用
@EnableHystrix
和@@HystrixCommand
注解 体验 Hystrix 服务熔断
package top.muquanyu.springcloud.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import top.muquanyu.springcloud.pojo.Dept;
import top.muquanyu.springcloud.service.DeptServiceImpl;
import java.util.List;
// 提供 RestFul 服务的 就只能是 Controller 接口
@RestController
public class DeptController {
@Autowired
private DeptServiceImpl deptService;
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "hystrixGet")
public Dept get(@PathVariable("id") Long id){
// 这个方法 其实 是有问题的,如果 id 传过来的 是空的呢。。
// 那么 我们 是不是 就查不到了?
Dept dept = deptService.queryByID(id);
if(dept == null){
throw new RuntimeException("id => "+ id + " 不存在该 Dept 对象");
}
return dept;
}
// 备选方案
public Dept hystrixGet(@PathVariable("id") Long id){
return new Dept().setDeptno(id).setDname("id => "+ id + " 没有对应的信息,null --@Hystrix").setDb_source("no this database in MySQL");
}
}
服务熔断 效果,实现 成功!
一个 可以显示 服务提供者 IP 地址的 配置:eureka.instance.perfer-ip-address: true