版权声明:转载请注明出处,谢谢! https://blog.csdn.net/qq_34872748/article/details/84964745
分布式系统面临的问题
扇出
多个微服务互相调用的时候,如果A调用B、C,而B、C又继续调用其他微服务,这就是扇出(像一把扇子一样慢慢打开。
服务雪崩
- 删除过程中,如果某一个环节的服务出现故障或连接超时,就会导致前面的服务占用越来越多的资源,进而引起系统崩溃,就是“雪崩效应”。
- 对于高流量的应用来说,单一的后端依赖会导致服务器所有的资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。
Hystrix介绍 - 熔断机制的注解是@HystrixCommand
- 熔断机制是应对雪崩效应的一种链路保护机制,一般存在于服务端
- 当扇出链路的某个服务出现故障或响应超时,会进行服务降级,进而熔断该节点的服务调用,快速返回“错误”的相应信息。、
- Hystrix的熔断存在阈值,缺省是5秒内20次调用失败就会触发
Hystrix源码
熔断案例
- 构建一个新的provider module
- pom.xml加入hystrix依赖(一定要配合Eureka)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
- application.xml中配置端口和Eureka信息(必配)和其他框架的配置信息(可选,如mybatis)
- 编写具体业务逻辑
- controller类中,在需要配置Fallback的方法上加入@@HystrixCommand(fallbackMethod = “XXX”)注解,XXX为FallBack方法名本例中作为测试所以抛出了异常
@ResponseBody
@GetMapping("/dept/{id}")
@HystrixCommand(fallbackMethod = "nullDeptFallBack")
public Dept findById(@PathVariable("id")Integer id) {
Dept dept = deptService.findById(id);
if (null == dept){
throw new RuntimeException("返回值为空!");
}
return dept;
}
- 根据需要配置FallBack的方法返回值编写代码
public Dept nullDeptFallBack(@PathVariable("id")Integer id) {
System.out.println(111);
return new Dept().setId(id).setDeptName("nullName").setDbSource("nullDB");
}
- 主启动类中加入@EnableCircuitBreaker注解
- 开启服务,测试
解耦与降级处理
降级
- 当系统整体资源快不够的时候,忍痛将部分服务暂时关闭,带渡过难关后,再重新开启。
- 降级处理时在客户端完成的,与服务端没有关系
- 理解:所谓降级,一般是从整体负荷考虑,当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的FallBack回调,返回一个缺省值。这样做虽然服务水平下降,但好歹可用,比直接挂掉好。
为什么要解耦
如果按照上面的熔断案例来做的话,Controller下的每个方法,都要给其编写一个FallBack方法,当方法慢慢变多,就会造成代码膨胀,一个是增加编写的工作量,另外一个也会增大维护的难度,代码的耦合度也会高,是十分不合理的,所以要将其解耦。
解耦思路
因为服务端的是通过实现接口访问服务端的,如果在父接口上实现了FallBack方法,通过这样一种方式去维护起来就能实现解耦,也顺便完成了降级的机制。
解耦&降级案例
- 在api模块中新建实现了FallbackFactory接口的类,其中泛型T就是我们需要维护其FallBack的接口方法,并实现其create方法,在create方法中返回实现了T的对象,使用匿名内部类实现T。==注意:这个类一定要加@Component注解!!
import com.XXX.entity.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class DeptClientServiceFallBackFactory implements FallbackFactory<DeptClientService> {
public DeptClientService create(Throwable throwable) {
return new DeptClientService() {
public boolean addDept(Dept dept) {
return false;
}
public List<Dept> findAll() {
return null;
}
public Dept findById(Integer id) {
return new Dept().setId(id).setDeptName("服务器跪了,").setDbSource("迟点来吧");
}
};
}
}
- 修改步骤1中传入的泛型T接口,添加@FeignClient(fallbackFactory = T.class)注解
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory = DeptClientServiceFallBackFactory.class)
public interface DeptClientService {
@PostMapping("/dept")
public boolean addDept(Dept dept);
@GetMapping("/dept")
public List<Dept> findAll();
@GetMapping("/dept/{id}")
public Dept findById(@PathVariable("id")Integer id);
}
- 修改consumer feign模块的application.xml文件,开启hystrix(注:在IDEA中可能没有代码提示,开启的true也没有正常高亮,但好像不需要做额外操作也不影响结果)
feign:
hystrix:
enabled: true
- 开启服务并测试