一、前言
在SpringCloud
微服务框架中,生产者提供消息注册到注册中心,消费者从注册中心获取生产者提供的服务接口调用地址,进行消息的消费;那么在SpringCloud
微服务中,消费者消费调用生产者的服务有两种形式:Rest+Ribbon
和Feign
这两种方式,Rest+Ribbon
在前面章节已经学习过,这里主要介绍下使用Feign
方式如何消费消息;
二、Feign是什么
Feign
是一个声明式的Web服务客户端工具,只要指定服务名,就可以将调用具体的服务接口,使用Feign
,只需要创建一个接口并注解。它具有可插拔的注解特性,可使用Feign
注解和JAX-RS
注解。Feign
支持可插拔的编码器和解码器。Feign默认集成了Ribbon组件,并和Eureka结合,并且默认是通过轮询实现了负载均衡的效果。 同时Spring Cloud
对 Feign
进行了增强,使Feign
支持 Spring Mvc
的注解,并整合了 Ribbon
等,从而让微服务的调用更加方便,Feign
客户端调用工具这才真正意义上实现了面向接口调用微服务。
1. 如何使用Feign
只需要创建一个接口,然后在上面添加@FeignClient(value = “服务名”)注解;
通过这个注解和指定的服务名称可以绑定远程微服务实例,服务名称可以大写也可以小写;
通过@RequestMapping(“/方法名”)来指定远程服务提供者提供的那个方法;
使用Feign,只需引入依赖: spring-cloud-starter-openfeign
组件即可; 仔细观察引入Feign
组件后的依赖信息:
Feign
默认集成了Hystrix
关于Feign
客户端调用工具,可以总结为以下三点:
-
Feign
采用的是基于接口的注解 -
Feign
整合了ribbon
,具有负载均衡的能力 -
Feign
整合了Hystrix
,具有服务保护、熔断的能力
三、环境准备
依据前面章节第二节搭建的springcloud-eureka-server
端口为8000
和springcloud-app-member
端口为8762
,先启动springcloud-eureka-server
端口为8000
的Eureka
注册中心;然后修改springcloud-app-member
中的getMember
接口,新增一个接受参数userName
,接下来启动会员服务两次,端口分别为8762和8765
,为了后续演示Feign
负载均衡效果,具体如下:
package com.thinkingcao.api.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc: 会员服务接口
* @author: cao_wencao
* @date: 2020-02-19 18:12
*/
@RestController
public class MemberController {
@Value("${server.port}")
private String serverPort;
//会员服务接口
@RequestMapping("/getMember")
private String getMember(@RequestParam("userName") String userName) {
return "我是会员服务,订单服务调用会员服务成功啦, 端口号为: " + serverPort +"——用户名: "+ userName;
}
}
四、创建一个Feign的服务
1. 新建springcloud-feign-client
在父工程的基础上新增module
,名字为springcloud-feign-client
,依赖如下:
<!--SpringBoot依赖版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.thinkingcao</groupId>
<artifactId>springcloud-feign-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-feign-client</name>
<description>SpringCloud整合Feign客户端组件消费服务</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<!--声明管理SpringCloud版本依赖信息-->
<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>
<dependencies>
<!-- SpringBootWeb组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springcloud整合eureka客户端组件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- springcloud整合Feign客户端组件 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--lombok代码简化工具-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2. 配置application.yml
##=========服务消费者-订单服务配置========
#服务端口号
server:
port: 8787
#定义服务名称(服务注册到eureka名称)
spring:
application:
name: app-thinkingcao-feign
#在此指定服务注册中心地址,将当前订单服务注册到eureka注册中心上
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8000/eureka
#启动注册操作,该值默认为true。若设置为fasle将不会启动注册操作。是否需要去检索寻找服务,默认是true
register-with-eureka: true
#是否需要从eureka上获取注册信息
fetch-registry: true
#表示eureka client间隔多久去拉取服务器注册信息,默认为30秒
registry-fetch-interval-seconds: 10
##心跳检测与续约时间(测试环境和本地开发环境将值设置小一点,保证服务关闭后,注册中心能够及时踢出)
instance:
#客户端向Eureka注册中心发送心跳的时间间隔,单位为秒(默认为30s),(客户端会按照此规则向Eureka服务端发送心跳检测包)
lease-renewal-interval-in-seconds: 2
#Eureka注册中心在收到客户端最后一次心跳之后等待的时间上限,单位为秒(默认为90s),超过时间则剔除(客户端会按照此规则向Eureka服务端发送心跳检测包)
lease-expiration-duration-in-seconds: 2
3. 创建一个Feign接口
定义一个feign接口,通过@FeignClient(“服务名”),来指定调用哪个微服务服务。比如我要调用springcloud-app-member中的getMember接口,则在接口中的方法@RequestMapping(“方法名”)注解中指定微服务的方法名字,表明调用该微服务实例中的哪一个方法,如果式企业开发中springcloud-app-member中声明了接口层,可直接用IFeignClientService 集成会员服务的接口,此时可以使用其全部的定义的方法,IFeignClientService 中无需再定义,这样方便简洁代码的开发;
- IFeignClientService如下
package com.thinkingcao.api.Feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @desc: Feign声明式客户端调用工具
* @author: cao_wencao
* @date: 2020-02-22 12:23
*/
@FeignClient(value = "app-thinkingcao-member")
public interface IFeignClientService {
//通过userId查询会员信息数据
@RequestMapping("/getMember")
public String getOrderToMemberInfo(@RequestParam("userName") String userName);
}
4. 暴露API接口
在Feign
微服务中的controller
层中,对外暴露一个"getOrderToMemberInfo"
的API
接口,通过上面定义的Feign
客户端IFeignClientService
来消费服务。代码如下:
- ApiOrderController
package com.thinkingcao.api.controller;
import com.thinkingcao.api.Feign.IFeignClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc:
* @author: cao_wencao
* @date: 2020-02-22 12:30
*/
@RestController
public class ApiOrderController {
@Autowired(required=false)
private IFeignClientService feignClientService;
@RequestMapping(value = "/getOrderToMemberInfo",method = RequestMethod.GET)
public String getOrderToMemberInfo(@RequestParam("userName") String userName){
String memberInfo = feignClientService.getOrderToMemberInfo(userName);
return memberInfo;
}
}
5. 启动类
通过@EnableFeignClients注解开启Feign客户端调用工具服务,通过@EnableEurekaClient注解开启Eureka客户端。表示向Eureka服务端注册和获取服务信息;
- AppFeignClient
package com.thinkingcao.api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class AppFeignClient {
public static void main(String[] args) {
SpringApplication.run(AppFeignClient.class, args);
}
}
6. 项目完整结构
五、测试
1. 测试
依次启动AppEurekaServer
、AppMemberProvider(启动两次,分别为
8762和8765端口)
、AppFeignClient
,多次访问请求:http://127.0.0.1:8787/getOrderToMemberInfo?userName=“Thinkingcao”,浏览器交替显示如下结果:
- 我是会员服务,订单服务调用会员服务成功啦, 端口号为: 8765——用户名: “Thinkingcao”
- 我是会员服务,订单服务调用会员服务成功啦, 端口号为: 8762——用户名: “Thinkingcao”
- 启动服务效果图
- - 8762效果图
- 8765效果图
2. 总结
- Feign默认支持负载均衡能力,默认使用的是轮询机制;
- Feign更适合于企业项目开发中服务消费的方式;
六、源码
1. 项目源码: https://github.com/Thinkingcao/SpringCloudLearning/tree/master/springcloud-feign