【微服务】Feign 远程调用

一、初识 Feign

1. 认识 Feign

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

存在下面的问题:

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

  2. 参数复杂URL难以维护

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

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

2. 使用 Feign

  1. 在子工程 pom 引入依赖

    <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
  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的依赖

    <dependency> <groupId>cn.itcast.demo</groupId> <artifactId>feign-api</artifactId> <version>1.0</version> </dependency>
  • 修改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 小时前
springCloud/Alibaba常用中间件之Setinel实现熔断降级
spring·spring cloud·中间件
码农飞哥2 小时前
互联网大厂Java求职面试实战:Spring Boot到微服务全景解析
java·spring boot·微服务·maven·hibernate·技术栈·面试技巧
胡斌附体7 小时前
微服务调试问题总结
java·微服务·架构·调试·本地·夸微服务联调
zc.z9 小时前
微服务如何实现服务的高并发
数据库·微服务·架构
why1519 小时前
微服务商城(1)开篇、服务划分
微服务·云原生·架构
qqxhb9 小时前
零基础学Java——第十一章:实战项目 - 微服务入门
java·开发语言·spring cloud·微服务
Wilson Chen10 小时前
Spring Cloud探索之旅:从零搭建微服务雏形 (Eureka, LoadBalancer 与 OpenFeign实战)
spring cloud·微服务·eureka
sg_knight11 小时前
从单体架构到微服务:架构演进之路
java·spring boot·spring·spring cloud·微服务·云原生·架构
华为云开发者联盟12 小时前
MCP与华为云CSE珠联璧合,打造AI时代微服务生态引擎
微服务·mcp·华为云ecs
eternal__day12 小时前
Spring Cloud:构建云原生微服务架构的最佳工具和实践
java·spring cloud·微服务·云原生·架构