序言
本文给大家介绍一下 Spring Cloud Feign 的基础概念以及使用方式。
一、远程调用
在传统的单体系统中,我们通常是客户端去请求服务端的接口。但是在分布式的系统中,常常需要一个服务去调用另外一个服务的接口。在服务端如何去调用另外一个服务端的接口呢?实现的方式有许多,例如:Spring 提供了一个 RestTemplate
类。
// 向容器注入 RestTemplate
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
// 引入 RestTemplate
@Resource
private RestTemplate restTemplate;
// 测试 RestTemplate
@Test
public void test() {
String str = restTemplate.getForObject("http://www.baidu.com", String.class);
System.out.println(str);
}
似乎,RestTemplate 能够实现 http 的远程调用,可以满足我们的需求了。但是这里有几个问题:
- 请求如果需要加上一些特殊的请求头呢
- 如果是 post 请求,数据如何传递呢
- 请求失败如何处理呢
我们发现:尽管 RestTemplate 能将上述问题都处理掉,但编码量会陡增,并且代码结构也会不太清晰。
二、Spring Cloud Feign
Spring Cloud Feign 是 Spring Cloud 生态系统中的一个组件,用于简化基于 RESTful 服务的客户端开发。它通过声明式的方式定义了对 REST 服务的接口,使得开发者可以像调用本地方法一样调用远程服务,而不需要手动构建 HTTP 请求和处理响应。Feign 还集成了 Ribbon 负载均衡和 Hystrix 断路器等功能,为微服务架构提供了更便捷的服务调用和容错机制。
Spring Cloud Feign 的主要特点包括:
- 声明式 REST 客户端:通过注解方式定义 REST 服务的接口,将远程服务的调用视为本地方法调用,降低了调用远程服务的复杂性。
- 集成 Ribbon 负载均衡:Feign 默认集成了 Ribbon,可以通过服务名进行服务发现和负载均衡,实现对多个服务实例的自动选择和负载分配。
- 集成断路器:Feign 可以集成 Hystrix 实现对服务调用的熔断、降级和容错处理,增强了系统的稳定性和可靠性。
- 支持 Spring Boot 自动配置:Feign 可以与 Spring Boot 无缝集成,提供自动配置和自定义配置的功能。
- 支持拦截器和解码器:Feign 支持自定义拦截器和解码器,用于实现请求和响应的增强处理。
- 支持与注册中心集成:Feign 可以与 Spring Cloud 的注册中心(如 Eureka、Consul 等)集成,实现动态的服务发现和调用。
Spring Cloud Feign 提供了一种简洁而强大的方式来进行微服务间的通信,使得开发者可以更加专注于业务逻辑的实现,而无需过多关注底层的通信细节。
三、快速入门
3.1 引入依赖
// 引入 openfeign 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
// 依赖版本
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>2.7.13</spring-boot.version>
<spring-cloud.version>2021.0.9</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
3.2 开启 openfeign 功能
@SpringBootApplication
// 注解开启 openfeign 功能
@EnableFeignClients
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
3.3 使用 openfeign
-
定义调用的接口
// 定义调用的地址和服务的名称 @FeignClient(name = "test", url = "http://127.0.0.1:8080") public interface TestClient { // 定义调用的接口 @GetMapping("/test/hello") String getInfo(); }
-
测试接口
@Autowired private TestClient testClient; @Test public void test0() { String str = testClient.getInfo(); System.out.println(str); }
-
测试效果
四、使用方式
openfeign 的使用方式和 Spring MVC 的使用方式基本一样。部分使用方式如下:
-
传递参数
@GetMapping("/stores") // 参数为 pageable Page<Store> getStores(Pageable pageable);
-
post 请求
// 可以使用 @PostMapping 表示 post 请求 @PostMapping(value = "/stores") Store update(Store store);
-
添加头信息
// 使用 @RequestHeader 表示头信息 @PostMapping("/stores") Store update(@RequestHeader("Authorization") String header, @RequestBody Store store);
五、断路器
在进行远程 http 调用的时候,并不能保证 100% 调用成功。为了解决调用接口时发生的异常,openfeign 提供了断路器。
5.1 引入断路器依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
5.2 开启断路器
feign:
circuitbreaker:
enabled: true
5.3 定义断路器的 fallback
// 定义一个断路器的 fallback
// 实现 TestClient
// 使用 @Component 注入到容器
@Component
public class TestClientFallback implements TestClient {
@Override
public String getInfo() {
return "发生了一个错误";
}
}
// 使用 fallback = TestClientFallback.class 指定 fallback
@FeignClient(name = "test", url = "http://127.0.0.1:8080", fallback = TestClientFallback.class)
public interface TestClient {
@GetMapping("/test/hello")
String getInfo();
}
5.4 使用效果
调用结果:
六、注册中心
// 定义调用的地址和服务的名称
@FeignClient(name = "test", url = "http://127.0.0.1:8080")
public interface TestClient {
// 定义调用的接口
@GetMapping("/test/hello")
String getInfo();
}
之前,我们直接配置了 url
。如果是微服务,微服务在注册中心注册了,可以直接按如下方式使用:
// 直接使用要调用的服务名称
@FeignClient(name = "test-service")
public interface TestClient {
// 定义调用的接口
@GetMapping("/test/hello")
String getInfo();
}
不过,在使用微服务调用时,新版本可能需要引入下面的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
七、FAQ
- 若是在 @Configuration 注解的类上使用 @EnableFeignClients 注解,要明确扫描位置,例如: @EnableFeignClients(basePackages = “com.example.clients”) ,@EnableFeignClients(clients = InventoryServiceFeignClient.class) 。否则,可能导致 @FeignClient 注解不生效
- spring-cloud-starter-openfeign 支持 spring-cloud-starter-loadbalancer。然而,由于它是一个可选的依赖项,如果你想使用它,需要手动将其添加到项目中。
往期推荐
- 缓存神器-JetCache
- Mybatis 缓存机制
- 为什么 MySQL 单表数据量最好别超过 2000w
- IoC 思想简单而深邃
- ThreadLocal