feign 使用基础

概述

Feign 是一个轻量级的 HTTP 请求调用框架,可以通过 Java 接口注解的方式进行 HTTP 请求。Feign 通过注解处理,将请求模板化。在实际调用时,传入参数,并根据参数应用到请求上,最终转化为真正的请求。该框架封装了 HTTP 调用流程,让其更加简单易用。

一、架构说明

Feign架构图

参考 新增微服务完成 CRUD,在操作时会新建一个包含两个模块的 Maven 微服务业务模块。

x
├── x-api     # api 模块主要存放实体、feign 调用接口
└── x-biz     # biz 模块主要存放具体的业务实现,其他模块不能直接导入

如上图所示,"服务调用方 X" 调用 "服务提供方 upms" 的相关接口。因此,"X" 服务需要引入 upms-api 的 Maven 模块。

模块引入注意事项

引入的是服务提供方的 API 模块,而不是引入 BIZ 模块

二、FeignClient 定义

FeignClient定义示意图

定义示例

以 upms 模块为例,展示如何定义 Feign 调用:

package com.pig4cloud.pigx.admin.api.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * Feign 客户端示例
 */
@FeignClient(contextId = "remoteUserService", value = "pigx-upms")
public interface RemoteUserService {
    
    /**
     * 根据用户ID获取用户信息
     * @param id 用户ID
     * @return 用户信息
     */
    @GetMapping("/user/info/{id}")
    R getUserInfo(@PathVariable("id") Long id);
}

关键要点

  • 模块位置:FeignClient 必须定义在 API 模块 中。如果服务提供方没有 API 模块(例如 mp/pay 等模块),则需要自己创建对应的 Maven API 模块,参考 upms-api 即可。
  • contextId 属性:代表 Bean 名称,在整个工程中必须唯一,避免命名冲突。
  • value 属性:代表服务提供方的名称(即注册中心的服务名)。
  • Mapping 路径:对应服务提供方接口路径(服务提供接口的 Controller Mapping + 接口 Mapping)。

三、SPI 文件声明

SPI文件配置示意图

将 FeignClient 所属类的全路径配置在 META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports 文件中:

com.pig4cloud.pigx.admin.api.feign.RemoteUserService
com.pig4cloud.pigx.admin.api.feign.RemoteDeptService
SPI配置重要性

虽然框架会自动扫描 com.pig4cloud.pigx 包下的所有 FeignClient,但在部分情况下,由于包名定义不规范,可能会导致 FeignClient 无法被扫描到,非常难以排查。因此,将 FeignClient 配置在 Spring SPI 文件中,可以确保在任何情况下都能正确加载相应的 FeignClient

四、Feign 超时配置

默认配置说明

Feign 默认的超时配置通常已经能够满足大部分业务场景的需求,不推荐通过全局配置文件覆盖所有接口的超时时间

针对特殊接口的超时配置

对于少数需要更长处理时间的接口(如文件上传、大数据量导出等),推荐使用 方法级别的超时配置

方式一:在调用时传入 Options 参数

import feign.Request;
import java.util.concurrent.TimeUnit;

// 创建自定义超时配置
Request.Options options = new Request.Options(
    5L, TimeUnit.SECONDS,    // 连接超时时间
    120L, TimeUnit.SECONDS,  // 读取超时时间
    true                     // 是否遵循重定向
);

// 调用时传入 options
remoteFileService.uploadLargeFile(file, options);

方式二:在 FeignClient 接口中定义

@FeignClient
public interface RemoteFileService {
    
    /**
     * 普通文件上传 - 使用默认超时配置
     */
    @PostMapping("/file/upload")
    R uploadFile(@RequestPart("file") MultipartFile file);
    
    /**
     * 大文件上传 - 自定义超时配置
     * @param file 文件
     * @param options 超时配置
     */
    @PostMapping("/file/upload/large")
    R uploadLargeFile(@RequestPart("file") MultipartFile file, Request.Options options);
    
    /**
     * 数据导出 - 自定义超时配置
     * @param query 查询条件
     * @param options 超时配置
     */
    @PostMapping("/data/export")
    R exportData(@RequestBody DataQuery query, Request.Options options);
}

配置参数说明

参数说明默认值推荐值
connectTimeout连接超时时间10秒5-10秒
readTimeout读取超时时间60秒根据业务调整
followRedirects是否遵循重定向truetrue

最佳实践建议

超时配置原则

大多数接口使用默认超时配置即可,无需额外配置。仅对文件上传/下载、大数据量查询、复杂报表生成、第三方接口调用等特殊场景考虑自定义超时。

  1. 保持默认配置:大多数接口使用默认超时配置即可,无需额外配置。
  2. 识别特殊场景:仅对以下场景考虑自定义超时:
    • 文件上传/下载
    • 大数据量查询
    • 复杂报表生成
    • 第三方接口调用
  3. 合理设置时间:根据实际业务需求设置超时时间,避免设置过长导致资源浪费。
  4. 添加注释说明:在代码中注释说明为什么需要自定义超时配置。
  5. 监控和调优:通过监控观察接口响应时间,适时调整超时配置。