【微服务】Feign 远程调用

一、初识 Feign

1. 认识 Feign

以前利用 RestTemplate 发送远程调用代码如下

存在下面的问题:

  1. 代码可读性差,编程体验不统一

  2. 参数复杂URL难以维护

Feign 是一个声明式的http客户端,官方地址:https://github.com/OpenFeign/feign

其作用就是帮助我们优雅的实现http请求的发送,解决上面提到的问题。

2. 使用 Feign

  1. 在子工程 pom 引入依赖

    org.springframework.cloud spring-cloud-starter-openfeign
  2. 在 order-service 的启动类添加注解开启 Feign 功能

  1. 编写 Feign 客户端, 创建接口

  1. 使用 Fegin, 将接口注入进来直接调用方法

到此 Feign 就替代了 RestTempate, 下面是 RestTempate 实现远程调用,是不是上面的更优雅呢。

3. 小结

使用 Feign 步骤

  1. 子模块引入引入 openfeign 依赖
  2. 子模块启动类添加 @EnableFeignClients 注解
  3. 子模块添加接口编写方法
  4. 使用 Feign 替代 RestTemplate

二、自定义配置

1. Feign 自定义配置介绍

类型 作用 说明
feign.Loger.Level 修改日志界别 包括四种不同的级别:none、basic、headers、full
feign.codec.Decoder 响应结果的解析器 http 远程调用的结果做解析,如解析json字符串作为java对象
feign.codec.Encoder 请求参数编码 将请求参数编码,便于通过http请求发送
feign.Contract 支持的注解格式 默认是SpringMVC的注解
feign.Retryer 失败重试机制 请求失败的重试机制,默认是没有,不过会使用Ribbon的重试

日志级别

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

2. 案例

2.1 配置文件方式

  1. 局部生效,写具体的服务名

    feign:
    client:
    config:
    userservice: # 写具体服务名称,针对某个微服务的配置
    loggerLevel: FULL # 日志级别

  2. 全局生效, default

    feign:
    client:
    config:
    default: # 使用default为全局配置
    loggerLevel: FULL # 日志级别

2.2 java 代码方式

  1. 声明一个类,然后声明一个 Logger.Level 的对象:

    public class DefaultFeignConfiguration {
    @Bean
    public Logger.Level logLevel() {
    return Logger.Level.BASIC; // 日志级别
    }
    }

  2. 选择生效范围

  • 如果局部生效,放在 @FeignClient 注解中

    @FeignClient(value = "userservice", configuration = DefaultFeignConfiguration .class)

  • 如果是全局生效,放在模块的启动类中的 @EnableFeignClients 注解上

    @EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration .class)

三、Feign 使用优化

Feign 底层发起 HTTP 请求是依赖其它框架的,Feign 底层客户端实现如下

  • URLConnection:默认实现,不支持连接池
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

因此优化 Feign 的性能主要包

  • 使用连接池代替默认的URLConnection
  • 日志级别最好用basic或none
  1. 引入依赖

在 order-service 的pom文件中引入 apache 的 httpclient依赖:

复制代码
<!--引入HttpClient依赖-->
  <dependency>
        <groupId>io.github.openfeign</groupId>
        <artifactId>feign-httpclient</artifactId>
  </dependency>
  1. 配置连接池

    feign:
    httpclient:
    enabled: true # 支持HttpClient的开关
    max-connections: 200 # 最大连接数
    max-connections-per-route: 50 # 单个路径的最大连接数

四、最佳实践

Feign 的 客户端与 Controller 代码很相似,

Feign 客户端代码片段

服务提供者的 Controller 代码片段

下面介绍如何优化这些重复的代码

1. 方式一(继承)

继承: 给消费者的 FeignClient 和 服务提供者 Controller 定义统一的父接口作为标准。但这种方式不太推荐。

缺点:

  • 耦合度太高,如果父接口变了,继承它的子类都要变。
  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

优点:

实现了代码共享

2. 方式二(抽取)

抽取: 将 FeignClient 抽取为独立模块,并且把接口有关的 POJO、默认的 Feign 配置放在这个模块中,提供给所有的消费者使用。

3. 基于抽取方式的案例

  1. 抽取:
  • 创建一个模块名为 feign-api 的模块
  • 在 feign-api 模块的 pom 引入依赖

    复制代码
    <!-- feign 依赖-->
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-starter-openfeign</artifactId>
          </dependency>
  • 把 order-service中编写的UserClient、User、DefaultFeignConfiguration复制到feign-api项目中。

  • 把 order-service 中 编写的UserClient、User、DefaultFeignConfiguration 删除,再 order-service 的 pom 文件中 引入 feign-api的依赖

    cn.itcast.demo feign-api 1.0
  • 修改order-service中的所有与上述三个组件有关的导包部分,改成导入feign-api中的包

  1. 测试

启动后发现报错了,找不到 UserClient 是什么情况呢?

原来是因为 userClient 在 cn.itcast.client 的包下,而 order-servcie 模块下调用 UserClient 是cn.itcast.order.service 包下,不在同个包下所以没有扫描出来

有两个解决方案:

**方案1:**启动类中指定Feign应该扫描的包:

复制代码
@EnableFeignClients(basePackages = "cn.itcast.client")

**方案2:**在启动类中指定需要加载的Client接口字节码:

复制代码
@EnableFeignClients(clients = {UserClient.class})
相关推荐
地瓜伯伯1 小时前
从MESI缓存一致性协议讲透synchronized的底层
java·spring boot·spring·spring cloud·微服务·springcloud
Devin~Y2 小时前
大厂 Java 面试实录:从音视频内容社区到 AI RAG 的全链路技术设计
java·spring boot·redis·spring cloud·微服务·kafka·音视频
就改了13 小时前
Windows 环境 SkyWalking 完整实操教程
windows·微服务·skywalking
worilb13 小时前
Spring Cloud 学习与实践(9):Gateway + JWT 统一鉴权
学习·spring cloud·gateway
山东点狮信息科技有限公司14 小时前
企业级 MES 制造执行系统架构设计与实践
spring cloud·性能优化·系统架构·策略模式·点狮
至乐活着20 小时前
Docker Compose多服务编排实战:从零搭建Node.js+MySQL+Redis全栈应用
docker·微服务·devops·容器编排·compose
就改了20 小时前
微服务异步场景链路断裂完整解决方案
微服务·云原生·架构
韩小兔修媛史21 小时前
SpringCloud八股文面试
spring·spring cloud·面试
shushangyun_21 小时前
批发商城系统源码多少钱?2026最新报价一览
java·开发语言·人工智能·spring·spring cloud
山东点狮信息科技有限公司1 天前
点狮OA-企业级 OA 办公自动化系统架构设计与实践
spring cloud·微服务·性能优化·架构·系统架构