文章目录
一.前言
在Spring Cloud - Ribbon负载均衡中,我们为大家了介绍了ribbon的简单应用。今天我们学习另一个客户端组件Feign,并且对比二者的异同。
二.什么是Feign?
Feign 是一个声明性的 web 服务客户端。 它使编写 web 服务客户端更加容易。 使用 Feign 创建一个接口并对其进行注释。 它具有可插拔的注释支持,包括 Feign 注释和 JAX-RS 注释。 Feign 还支持可插拔编码器和解码器。 Spring Cloud 增加了对 Spring MVC 注释的支持,以及对使用 Spring Web 默认使用的 HttpMessageConverters 的支持。 Spring Cloud 集成了 Ribbon 和 Eureka,以及 Spring Cloud LoadBalancer,以便在使用 Feign 时提供负载平衡的 http 客户端。
三.Ribbon、Feign和OpenFeign的区别
相信大家和我一样会有疑问,了解完Ribbon,Feign,OpenFeign之后,我们发现三者好像很相似。那么他们之间到底有什么不同?
3.1 Ribbon
Ribbon 是 Netflix开源的基于HTTP和TCP等协议负载均衡组件
Ribbon 可以用来做客户端负载均衡,调用注册中心的服务
Ribbon的使用需要代码里手动调用目标服务,请参考官方示例
3.2 Feign
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
Feign支持的注解和用法请参考官方文档
Feign本身不支持Spring MVC的注解,它有一套自己的注解
3.3 OpenFeign
OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等等。
OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,
并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
更多内容,大家可以阅读Ribbon、Feign和OpenFeign的区别
四.创建项目
经过上面一顿骚操作,我们的模块就成功创建了springcloud-openfeign
五.配置项目
5.1 springcloud-openfeign
5.1.1 添加@EnableFeignClients和@EnableDiscoveryClient注解
/**
* OpenFeign
* @author milogenius
* @date 2020/3/16 21:11
* @version v1.0.0
* @description
*/
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class OpenFeignApplication {
public static void main(String[] args) {
SpringApplication.run(OpenFeignApplication.class, args);
}
}
5.1.2 pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.milo</groupId>
<artifactId>milgenius-springcloud</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.milo</groupId>
<artifactId>springcloud-openfeign</artifactId>
<version>1.0.0</version>
<name>springcloud-openfeign</name>
<description>openfeign学习项目</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR5</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
5.1.3 application.yml
## 注册中心
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
server:
port: 8766
spring:
application:
name: service-openfeign
5.1.4 相关代码
ConsumerClient
/**
* @author milogenius
* @date 2020/3/160:03
* @description
*/
@FeignClient("service-provider")
@Component
public interface ConsumerClient {
@GetMapping("/hello")
String hello();
}
ConsumerController
/**
* @author: Milogenius
* @create: 2019-06-28 13:45
* @description:
**/
@RestController
public class ConsumerController {
@Autowired
private IConsumerService consumerService;
@RequestMapping(value = "/hello",method = RequestMethod.GET)
public String index(@RequestParam String name){
return consumerService.hello(name);
}
}
IConsumerService
/**
* @author: Milogenius
* @create: 2019-06-28 13:48
* @description:
**/
public interface IConsumerService {
String hello(String name);
}
ConsumerServiceImpl
/**
* @author: Milogenius
* @create: 2019-06-28 13:49
* @description:
**/
@Service
public class ConsumerServiceImpl implements IConsumerService {
//注入client
@Autowired
private ConsumerClient client;
@Override
public String hello(String name) {
return client.hello();
}
}
至此,springcloud-openfeign
模块我们就配置完成
5.2 springcloud-eureka-server 和 springcloud-service-provider
关注我文章的同学应该都知道,服务注册中心和服务提供者,我已经在Spring Cloud - Eureka Server和Spring Cloud - Eureka Client中简单给大家介绍过,大家可以阅读创建,或者可以直接下载源码进行测试;
六.案例测试
首先,我们启动注册中心springcloud-eureka-server
接着,我们启动springcloud-openfeign
下面,我们启动三个服务,在启动之前,需要阅读如何在IntelliJ Idea中同时启动不同端口的两个实例
如上图所示,依次修改端口号启动三个服务;
至此,我们项目启动完成;
接下来,我们测试一下openfeign:
通过上面的图片,我们可以看到请求负载到了我们的三个服务,也验证了openfeign是基于ribbon实现;
七. 结论
- 创建client时候,要注意服务的路径和请求方式,务必保持一致;
- 使用
@requestBody
时候,应该使用@postmapping()
- 多个参数时候,通过@RequestParam(“id”) int id 方式调用
参考文章
[1].Ribbon、Feign和OpenFeign的区别[N] 持盾的紫眸
示例代码
milogenius-springcloud
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=20xnahvv3r9c4