OpenFeign
OpenFeign 介绍
OpenFeign 是什么
OpenFeign 是个声明式 WebService 客户端,使用 OpenFeign 让编写 Web Service 客户端 更简单
它的使用方法是定义一个服务接口然后在上面添加注解
OpenFeign 也支持可拔插式的编码器和解码器。
Spring Cloud 对 OpenFeign 进行了封装使其支持了 Spring MVC 标准注解和 HttpMessageConverters
OpenFeign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡
官网
https://github.com/spring-cloud/spring-cloud-openfeign
Feign 和 OpenFeign 区别
Feign
Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端
Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
Feign的使用方式是:使用Feign的注解定义接口,调用服务注册中心的服务
Feign支持的注解和用法请参考官方文档:https://github.com/OpenFeign/feign
Feign本身不支持Spring MVC的注解,它有一套自己的注解
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
OpenFeign
OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如 @RequesMapping等等。
OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口
OpenFeign通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
精简一句话:OpenFeign 就是在 Feign 基础上做了加强 , 有些程序员为了方便,说 Feign 就是指的 OpenFeign
应用实例
示意图

创建服务消费模块 -通过 OpenFeigen 实现远程调用
参考 member-service-consumer-80 创建 member-service-consumer-openfeign-80(具体步 骤参考以前)
修改 pom.xml
<!--引入相关的依赖-->
<dependencies>
<!--引入openfeign-starter 就是场景启动器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!--引入eureka-client 场景启动器starter: 使用版本仲裁-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--引入web-starter 我们使用版本仲裁(从父项目继承了版本)-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--说明:starter-actuator 是springboot程序的监控系统, 可以实现系统的健康检测
可以通过http://localhost:80/actuator 看到相关的连接,和信息
-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--引入e_commerce_center-common-api-->
<!--version=1.0-SNAPSHOT-->
<!--groupId=com.lzw.springcloud-->
<!--artifactId=e_commerce_center-common-api-->
<dependency>
<groupId>com.lzw</groupId>
<artifactId>e_commerce_center-common-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
创建 application.yml 内容如下:
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign
# 配置 eureka client
eureka:
client:
register-with-eureka: true # 将自己注册到Eureka-server
fetch-registry: true # 表示从 Eureka-server 抓取注册信息
service-url:
#表示将自己注册到哪个eureka-server
# defaultZone: http://localhost:9001/eureka
defaultZone: http://eureka9001.com:9001/eureka,http://eureka9002.com:9002/eureka
创建主启动类
package com.lzw.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @author LiAng
* @time 2022/11/6 9:11
*/
@SpringBootApplication
@EnableEurekaClient
//启动OpenFeignClient
@EnableFeignClients
public class MemberConsumerOpenfeignApplication {
public static void main(String[] args) {
SpringApplication.run(MemberConsumerOpenfeignApplication.class, args);
}
}
创建 MemberFeignService.java
package com.lzw.springcloud.service;
import com.lzw.springcloud.entity.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @author LiAng
* @time 2022/11/6 9:14
*/
@Component
@FeignClient(value = "MEMBER-SERVICE-PROVIDER")
public interface MemberFeignService {
/**
* 1. 远程调用的方式是get
* 2. 远程调用的url http://ip:port/member/get/{id}
* http://MEMBER-SERVICE-PROVIDER/member/get/{id}
* 3. MEMBER-SERVICE-PROVIDER 是 服务提供方在 Eureka Server 注册的服务
* 4. openfeign 会根据负载均衡来决定调用 10000/10002-默认是轮询
* 5. 因为openfeign 好处是支持了springmvc注解 + 接口解耦
* @param id
* @return
*/
@GetMapping("/member/get/{id}")
public Result getMemberById(@PathVariable("id") Long id);
}
创建 MemberConsumerFeignController.java
package com.lzw.springcloud.controller;
import com.lzw.springcloud.entity.Result;
import com.lzw.springcloud.service.MemberFeignService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author LiAng
* @time 2022/11/6 9:20
*/
@RestController
public class MemberConsumerFeignController {
//装配 MemberFeignService
@Resource
private MemberFeignService memberFeignService;
@GetMapping(value = "/member/consumer/openfeign/get/{id}")
public Result getMemberById(@PathVariable("id") Long id){
return memberFeignService.getMemberById(id);
}
}
测试
浏览器输入 : http://localhost/member/consumer/openfeign/get/1
观察访问的 10000/10002 端口的服务是轮询的
注意事项和细节
配Openfeign的使用特点是 微服务调用接口+@FeignClient , 使用接口进行解耦
@FeignClient(value = "MEMBER-SERVICE-PROVIDER"), 这里 MEMBER-SERVICE-PROVIDER就是Eureka Server服务提供方注册的名称, 不要写错了
接口方法上: value是不能乱写, 远程调用的url 为
http://MEMBER-SERVICE-PROVIDER/member/get/{id}
@GetMapping(value = "/member/get/{id}")
public Result<Member> getMembertById(@PathVariable("id") Long id);
日志配置
基本介绍
- 说明: Feign 提供了日志打印功能,可以通过配置来调整日志级别,从而对 Feign 接口的 调用情况进行监控和输出
- 日志级别
NONE∶默认的,不显示任何日志
BASIC∶仅记录请求方法、URL、响应状态码及执行时间;
HEADERS∶除了 BASIC中定义的信息之外,还有请求和响应的头信息;
FULL∶除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据

配置日志-应用实例
在 member-service-consumer-openfeign-80 创建 com/lzw/springcloud/config/OpenFeignConfig.java
package com.lzw.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author LiAng
* @time 2022/11/6 10:32
*/
@Configuration
public class OpenFeignConfig {
@Bean
public Logger.Level loggerLever(){
return Logger.Level.FULL;
}
}
修改 application.yml
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign
# 配置 eureka client
eureka:
client:
register-with-eureka: true # 将自己注册到Eureka-server
fetch-registry: true # 表示从 Eureka-server 抓取注册信息
service-url:
#表示将自己注册到哪个eureka-server
# defaultZone: http://localhost:9001/eureka
defaultZone: http://eureka9001.com:9001/eureka,http://eureka9002.com:9002/eureka
logging:
level:
# 对 MemberFeignService 接口调用过程打印信息-Debug
com.lzw.springcloud.service.MemberFeignService: debug
常见的日志级别有 5 种,分别是 error、warn、info、debug、trace
error:错误日志,指比较严重的错误,对正常业务有影响,需要运维配置监控的;
warn:警告日志,一般的错误,对业务影响不大,但是需要开发关注;
info:信息日志,记录排查问题的关键信息,如调用时间、出参入参等等;
debug:用于开发 DEBUG 的,关键逻辑里面的运行时数据;
trace:最详细的信息,一般这些信息只记录到日志文件中。
别忘了,撤销测试日志配置
OpenFeign 超时
先看一个问题
修改 member-service-provider-10000/10002 的 com/lzw/springcloud/controller/MemberController.java
@GetMapping("/member/get/{id}")
public Result getMemberById(@PathVariable("id") Long id) {
//模拟超时
try {
TimeUnit.MILLISECONDS.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
...
...
}
浏览器访问 http://localhost/member/consumer/openfeign/get/1
,此时会出现超时错误

原因分析: OpenFeign 默认超时时间 1 秒钟 ,即等待返回结果 1 秒
设置超时时间
在某些情况下,一个服务调用时间可能要超过 1 秒,就需要重新设置超时时间
修改 member-service-consumer-openfeign-80 的 application.yml
server:
port: 80
spring:
application:
name: member-service-consumer-openfeign
# 配置 eureka client
eureka:
client:
register-with-eureka: true # 将自己注册到Eureka-server
fetch-registry: true # 表示从 Eureka-server 抓取注册信息
service-url:
#表示将自己注册到哪个eureka-server
# defaultZone: http://localhost:9001/eureka
defaultZone: http://eureka9001.com:9001/eureka,http://eureka9002.com:9002/eureka
logging:
level:
# 对 MemberFeignService 接口调用过程打印信息-Debug
com.lzw.springcloud.service.MemberFeignService: debug
ribbon:
# 1.设置feign客户端超时时间(openfeign默认支持ribbon)
# 2.ReadTimeout:8000,建立连接从服务提供方获取可用资源的所用的全部时间
# 3.时间单位是毫秒
ReadTimeout: 8000
# 两端连接所用时间
ConnectionTimeout: 8000
测试,等待5秒后会收到正确响应
记得撤销超时测试代码和配置