分布式系统面临的问题:
复杂分布式系统结构中应用程序有数十个依赖关系,每个依赖关系在某些时候都会不可避免的失败。
服务雪崩
如上图:多个服务调用时,假设正常流程是 服务A调用服务D,再调用服务C1,再调用服务D1,最后调用D;若出现服务D1出现故障,响应时间过程长或者无法得到响应。对此服务的调用会占用越来越多的资源,进而引起系统崩溃。这就是“服务雪崩”。
对于高流量应用来说,单一的后端依赖可能会导致服务器上所有的资源几秒内饱和,比失败更糟的是,这些应用程序可能还会导致服务之间的延迟增加,备份队列,线程和其他资源紧张等一系列“蝴蝶效应”。这些都需要对故障的隔离和管理,不能取消整个系统或整个程序。
Hystrix
Hystrix是一个用于处理分布式系统延迟和容错的开源库,他能够保证一个服务出现问题的情况下,不会导致整体服务的失败,避免连级故障,提高分布式系统的弹性。
“断路器”本身是一种开关装置,的那个某个服务单元发生故障时,通过断路器的故障监控(类似于熔断保险丝),向调用方法返回一个预期的 ,已设置好的,可处理备选响应(FallBack),而不是长时间等待或者抛出调用方法无法处理的异常,,从而避免了故障在分布式的蔓延,乃至雪崩。
作用
- 服务降级
- 服务熔断
- 服务限流
- 接近实时的监控
服务熔断
熔断机制是对应雪崩效应的一种微服务链路保护机制
当某个服务出现故障时,会进行服务降级,进而熔断该节点的服务调用,快速返回提示信息,当监测到该节点恢复正常后则恢复调用链路,在SpringCloud的框架里利用@HystrixCommand来实现,会监控服务间的调用的状况。缺省是5秒内调用20次失败则会启动服务降级。服务端
1.以上一个提供者为例,复制一个相同的模块,并添加Hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
修改服务名称信息
方法演示:
当查询特定的dept时,传入的id为空或者没有此id,则会进入 @HystrixCommand(fallbackMethod=“指定方法“),也就是定义的备选方法,
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean addDept(Dept dept){
return deptService.addDept(dept);
}
@GetMapping("/dept/get/{id}")
@HystrixCommand(fallbackMethod = "getDeptByIdHystrix")
public Dept getDeptById(@PathVariable("id") Long id){
Dept dept=deptService.queryById(id);
if (dept==null){
throw new RuntimeException("不存在该用户,或用户信息无法找到");
}
return dept;
}
@GetMapping("/dept/getAll")
public List<Dept> queryAll(){
return deptService.queryAll();
}
//备选方法
public Dept getDeptByIdHystrix(@PathVariable("id") Long id){
return new Dept().setDeptNo(id)
.setDb_source("无")
.setDb_source("无");
}
}
2.主启动类开启注解功能,添加对熔断的支持
3.启动Eureka,服务提供者 消费者测试:
测试存在的数据:
测试不存在数据
1.未开启服务熔断:
2.开启服务熔断:
发现测试不存在的数据时,并不会像之前一样出现500错误,而是出现自定义的信息,大大提升了用户的体验。
服务降级
如上图:有三个服务,每个服务中有多个微服务,若某一时刻,请求数如上图,A服务有大量请求数,B和C服务只有少量,这种情况下,当请求B和C的服务用户,会通知用户服务关闭进行服务降级,用来度过A服务的高并发情况。客户端
1.实现接口,编写代码
编写回调返回的类:实现FallbackFactory接口,失败时返回的接口需要重写里面的全部方法。
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory {
@Override
public Object create(Throwable throwable) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept().setDeptNo(id)
.setDName("Fail")
.setDb_source("本服务器已关闭");
}
@Override
public List<Dept> queryAll() {
return null;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
};
}
}
2.客户端中开启服务降级
测试:
客户端访问添加了服务降级的 服务时,会提示此服务不可访问 不可用。
总结
服务熔断:服务端,某个服务超时或者异常,引起熔断 保险丝
服务降级:客户端,从整体网站负载请求考虑,当某个服务熔断或者关闭之后,将不再被调用,此时在客户端可以准备一个FallbackFactory,赶回一个默认的值。
服务监控
1.导入相关依赖hysrix 和hystrix-dashboard,
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
并且服务端都要有监控依赖:
<!-- 完善监控信息-->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.配置端口:
3.开启注解:
访问9001端口,注意访问的路径,会出现以下网页:
看到页面提示后,需要在服务提供者中添加被监控bean,返回访问的路径(固定代码):
测试:
当向这个服务发送多次请求后,监控页面也会随之监控服务的请求次数和心跳次数以及调用的方法、服务请求频率 断路
各种图标含义:
- 实心圆:通过颜色变化代表实例的健康程度:绿色>黄色>橙色>红色,实心圆的大小代表实例的请求次数,请求次数越多,实心圆越大。
- 曲线:用来记录两分钟内的流量变化,可通过观察流量的上升或者下降趋势
实例未被请求后,心跳停止,变为以上状态。