【微服务】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})
相关推荐
WeiLai11123 小时前
面试基础--微服务架构:如何拆分微服务、数据一致性、服务调用
java·分布式·后端·微服务·中间件·面试·架构
茶本无香5 小时前
kafka+spring cloud stream 发送接收消息
spring cloud·kafka·java-zookeeper
Swift社区5 小时前
【微服务优化】ELK日志聚合与查询性能提升实战指南
spring·elk·微服务·云原生·架构
陌殇殇9 小时前
002 SpringCloudAlibaba整合 - Feign远程调用、Loadbalancer负载均衡
java·spring cloud·微服务
m0_6754470818 小时前
Java版企电子招标采购系统源业码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis
java·spring cloud·企业电子招投标系统源码·招投标系统源码
LUCIAZZZ19 小时前
EasyExcel快速入门
java·数据库·后端·mysql·spring·spring cloud·easyexcel
落落落sss19 小时前
MongoDB
数据库·windows·redis·mongodb·微服务·wpf
黄名富20 小时前
Spring Cloud — 深入了解Eureka、Ribbon及Feign
分布式·spring·spring cloud·微服务·eureka·ribbon
LUCIAZZZ21 小时前
SkyWalking快速入门
java·后端·spring·spring cloud·微服务·springboot·skywalking
m0_7482451721 小时前
SpringCloud-使用FFmpeg对视频压缩处理
spring·spring cloud·ffmpeg