【微服务】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})
相关推荐
万物皆字节7 小时前
spring cloud负载均衡之FeignBlockingLoadBalancerClient、BlockingLoadBalancerClient
spring cloud
掘金-我是哪吒9 小时前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
Ken_11159 小时前
SpringCloud系列(49)--SpringCloud Stream消息驱动之实现生产者
spring cloud
DavidSoCool11 小时前
RabbitMQ使用topic Exchange实现微服务分组订阅
分布式·微服务·rabbitmq
掘金-我是哪吒12 小时前
分布式微服务系统架构第158集:JavaPlus技术文档平台日更-JVM基础知识
jvm·分布式·微服务·架构·系统架构
Kookoos14 小时前
ABP VNext + Tye:本地微服务编排与调试
微服务·云原生·架构·tye
guojl18 小时前
Ribbon原理和源码分析
spring cloud·微服务
掘金-我是哪吒19 小时前
分布式微服务系统架构第157集:JavaPlus技术文档平台日更-Java多线程编程技巧
java·分布式·微服务·云原生·架构
掘金-我是哪吒19 小时前
分布式微服务系统架构第155集:JavaPlus技术文档平台日更-Java线程池实现原理
java·分布式·微服务·云原生·架构
Code季风1 天前
深入理解微服务中的服务注册与发现(Consul)
java·运维·微服务·zookeeper·架构·go·consul