Ribbon和Feign是什么?
Ribbon 和 Feign是spring cloud实现服务调用的重要组件,是基于http请求的实现客户端负载均衡调用其他服务的组件,是一个HTTP客户端工具类框架,不需要单独部署,直接作为jar引入到项目中使用(但是还需要已有注册中心)。Feign 是在 Ribbon的基础上进行了一次改进,可以更优雅而简单的实现了服务调用。
为什么使用Ribbon、Feign这两个组件?
在没有使用ribbon、feign之前,我们怎么调用其他服务的HTTP接口? 调用其他服务的http接口,我们一般使用HttpClient 或 RestTemplate访问其他服务的接口,但是这样访问我们需要显示指定访问的服务的IP地址和端口,在以前的单体架构没有问题,但是在spring cloud架构的集群里面,一个服务可以部署在多台服务器,而且服务的IP和端口也可能变更,所以,Ribbon和Feign组件正是为了解决这个问题的工具。
引入Ribbon、Feign后,我们的微服务会从eruke或者nacos的注册中心拿到可以访问该服务的IP地址+端口的列表,然后缓存到本地,然后通过Ribbon组件里面的负载均衡策略去决定去调用那一个IP地址的服务实例,这样我们调用其他服务就不需要显示指定IP地址和端口
注:
- Ribbon默认的负载均衡策略是轮询,Feign是封装了Ribbo的,所以也是默认轮询
- Ribbon、Feign都是客户端的负载均衡,即由调用的客户端决定访问那一台服务器。而Nginx则是服务端负载均衡,访问的服务器由服务端决定,客户端无法决定访问的具体服务器。
- Ribbon、Feign已经停止更新了,OpenFeign 是 spring cloud 在 Feign 的基础上开发出来且支持 spring mvc注解,下面的demo使用的是OpenFeign
记录Ribbon、OpenFeign的使用demo
1.创建服务提供者的微服务
服务端的接口代码
@RestController
@RequestMapping(value = "/product")
public class ProductController {
@Value("${spring.application.name}")
private String projectName;
@Value("${server.port}")
private String port;
@RequestMapping(value = "/service_hello")
public String serviceHello(){
return String.format("服务名称:%s:%s ,Hello我是服务提供者,提供服务",projectName,port);
}
}
启动不同端口的多个相同的服务提供者,port为9002,9003
启动后可以在nacos的控制台看到服务名称为product-service的服务有两个实例
2.使用Ribbon的demo
- 在springcloud项目不需要引入格外依赖,我们引入注册中心的eureka或nacos的包里面已经包含了相关的依赖,我这里引入注册中心nacos的依赖
注:
我这里的项目是springboot2+srpingcloud alibaba nacos,这里的依赖可参考这篇:spring cloud 使用nacos作为注册中心
- 在restTemplate的bean上加入注解@LoadBalanced
- 使用restTemplate调用服务的地方由原来的ip+端口修改为服务名称
- 修改完启动项目可以正常访问服务提供者,并且是轮询访问两个服务实例
2.使用OpenFeign的demo
- 引入依赖
<!-- feign组件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 在主类上加入Feign的注解@EnableFeignClients
- 消费者创建一个使用Feign声明调用服务的接口
@FeignClient("product-service")//@FeignClient注解声明提供者的服务名称
public interface PorductService {
/**
* 指定调用提供者的哪个接口,value指定的是服务的接口地址
* @return
*/
@RequestMapping(value = "/product/service_hello")
String serviceHello();
}
- 修改controllor,使用feign声明的service调用服务
- 启动服务测试验证
注:
建议大家将接口的消费定义,单独抽一个项目出来,后面打成公共的jar,这样无论是哪个项目需要调用接口,引入公共的接口SDK jar即可,不用重新定义一遍