SpringCloud基础(6)– OpenFeign与熔断和降级

Feign和RestTemplate一样,也是HTTP客户端请求工具,但是它的使用方式更加便捷。本章,我们学习OpenFeign以及服务熔断和降级的概念

首先我们添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在启动类添加注解@EnableFeignClients

@SpringBootApplication
@EnableFeignClients
public class BorrowApplication {
    public static void main(String[] args) {
        SpringApplication.run(BorrowApplication.class, args);
    }
}

那么如果我们需要调用其他微服务提供的接口,直接创建该服务对应的接口类即可:

@FeignClient("userservice")   //声明为userservice服务的HTTP请求客户端
public interface UserClient {
    //路径保证和其他微服务提供的一致即可
    @RequestMapping("/user/{uid}")
    User getUserById(@PathVariable("uid") int uid);  //参数和返回值也保持一致
}

上面我们的借阅服务需要使用到用户服务接口,我们只需要创建UserClient接口类并进行配置即可。

这样我们直接调用这个接口即可实现接口调用,并同时会实现负载均衡。

服务熔断和降级

我们知道,微服务之间是可以进行相互调用的,那么如果出现了下面的情况会导致什么问题?

由于位于最底端的服务提供者E发生故障,那么此时会直接导致服务ABCD全线崩溃,就像雪崩了一样。

这种问题实际上是不可避免的,由于多种因素,比如网络卡顿、系统故障、硬件问题等,都存在一定可能,会导致这种极端的情况发生。因此,我们需要寻找一个应对这种极端情况的解决方案。

为了解决分布式系统的雪崩问题,SpringCloud提供了Hystrix熔断器组件,他就像我们家中的保险丝一样,当电流过载就会直接熔断,防止危险进一步发生,从而保证家庭用电安全。可以想象一下,如果整条链路上的服务已经全线崩溃,这时还在不断地有大量的请求到达,需要各个服务进行处理,肯定是会使得情况越来越糟糕的。

首先我们来看看服务降级,注意一定要区分开服务降级和服务熔断的区别,服务降级并不会直接返回错误,而是可以提供一个补救措施,正常响应给请求者。这样相当于服务依然可用,但是服务能力肯定是下降了的。

熔断机制是应对雪崩效应的一种微服务链路保护机制,当检测出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回”错误”的响应信息。当检测到该节点微服务响应正常后恢复调用链路。

实际上,熔断就是在降级的基础上进一步升级形成的,也就是说,在一段时间内多次调用失败,那么就直接升级为熔断。

但Hystrix的依赖已经停止维护,因此这部分我们日后再谈

OpenFeign实现降级

Feign都是以接口的形式来声明远程调用,而降级的场景基本是远程调用失败,那么既然远程调用已经失效,我们就自行对其进行实现,创建一个实现类,对原有的接口方法进行替代方案实现:

@Component   //注意,需要将其注册为Bean,Feign才能自动注入
public class UserFallbackClient implements UserClient{
    @Override
    public User getUserById(int uid) {   //这里我们自行对其进行实现,并返回我们的替代方案
        User user = new User();
        user.setName("我是替代方案");
        return user;
    }
}

实现完成后,我们只需要在原有的接口中指定失败替代实现即可:

//fallback参数指定为我们刚刚编写的实现类
@FeignClient(value = "userservice", fallback = UserFallbackClient.class)
public interface UserClient {

    @RequestMapping("/user/{uid}")
    User getUserById(@PathVariable("uid") int uid);
}

最后我们在配置文件中开启熔断支持:

feign:
  circuitbreaker:
    enabled: true