跳到主要内容

配置详解

OpenFeign 提供了灵活的配置机制,支持全局配置和客户端级别配置。本章将深入讲解各种配置选项及其使用场景。

配置方式概览

OpenFeign 支持三种配置方式:

  1. Java 配置类:使用 @Configuration 定义配置 Bean
  2. YAML 配置文件:在 application.yml 中配置
  3. Feign Builder API:编程式构建客户端

这三种方式可以组合使用,优先级为:YAML 配置 > Java 配置 > 默认配置。

全局配置

YAML 全局配置

application.yml 中配置所有 Feign 客户端的默认行为:

spring:
cloud:
openfeign:
client:
config:
default: # default 表示全局默认配置
connectTimeout: 5000 # 连接超时(毫秒)
readTimeout: 10000 # 读取超时(毫秒)
loggerLevel: full # 日志级别
dismiss404: false # 是否忽略 404 错误
decodeSlash: true # 是否解码斜杠

Java 全局配置

使用 @EnableFeignClientsdefaultConfiguration 属性:

@EnableFeignClients(
basePackages = "com.example.clients",
defaultConfiguration = GlobalFeignConfig.class
)
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

定义全局配置类:

public class GlobalFeignConfig {

@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}

@Bean
public Request.Options requestOptions() {
return new Request.Options(5000, 10000); // 连接超时 5s,读取超时 10s
}

@Bean
public Retryer retryer() {
return new Retryer.Default(100, 1000, 3); // 初始间隔 100ms,最大间隔 1s,最多重试 3 次
}
}

客户端级别配置

YAML 客户端配置

针对特定客户端进行配置,客户端名称对应 @FeignClientnamevalue 属性:

spring:
cloud:
openfeign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 10000
user-service: # 针对 user-service 客户端的配置
connectTimeout: 3000
readTimeout: 5000
loggerLevel: headers
requestInterceptors:
- com.example.interceptors.AuthInterceptor
errorDecoder: com.example.decoder.CustomErrorDecoder

Java 客户端配置

@FeignClient 中指定配置类:

@FeignClient(
name = "user-service",
configuration = UserFeignConfig.class
)
public interface UserClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}

定义客户端配置类:

public class UserFeignConfig {

@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.HEADERS;
}

@Bean
public RequestInterceptor authInterceptor() {
return template -> {
template.header("Authorization", "Bearer token");
};
}

@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}
}
配置类不要加 @Configuration

虽然配置类可以添加 @Configuration 注解,但这会导致该配置成为全局配置。建议不加 @Configuration,或者将其放在 @ComponentScan 扫描范围之外。

核心配置项详解

超时配置

OpenFeign 有两个超时参数:

  • connectTimeout:建立连接的超时时间
  • readTimeout:从建立连接到接收响应的超时时间
spring:
cloud:
openfeign:
client:
config:
default:
connectTimeout: 5000 # 5 秒连接超时
readTimeout: 30000 # 30 秒读取超时

超时时间设置建议

场景connectTimeoutreadTimeout
普通业务接口3-5 秒10-30 秒
文件上传/下载5-10 秒60-300 秒
批量处理接口5 秒60-120 秒

日志级别

OpenFeign 支持四种日志级别:

级别说明
NONE不记录日志(默认)
BASIC记录请求方法、URL、响应状态码和执行时间
HEADERS记录 BASIC 级别信息 + 请求和响应头
FULL记录 HEADERS 级别信息 + 请求和响应体

配置示例:

# YAML 配置
spring:
cloud:
openfeign:
client:
config:
user-service:
loggerLevel: full

# 同时需要配置 Logger 级别
logging:
level:
com.example.clients.UserClient: DEBUG
// Java 配置
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}

重试机制

默认情况下,OpenFeign 禁用重试。可以通过配置 Retryer 启用:

public class FeignConfig {

// 启用默认重试:初始间隔 100ms,最大间隔 1s,最多重试 5 次
@Bean
public Retryer retryer() {
return new Retryer.Default();
}

// 自定义重试参数
@Bean
public Retryer customRetryer() {
// period: 初始重试间隔
// maxPeriod: 最大重试间隔
// maxAttempts: 最大重试次数
return new Retryer.Default(100, 1000, 3);
}

// 禁用重试
@Bean
public Retryer noRetry() {
return new Retryer.NEVER_RETRY;
}
}

自定义重试逻辑

public class CustomRetryer implements Retryer {

private final int maxAttempts;
private final long period;
private int attempt;

public CustomRetryer(int maxAttempts, long period) {
this.maxAttempts = maxAttempts;
this.period = period;
this.attempt = 1;
}

@Override
public void continueOrPropagate(RetryableException e) {
if (attempt++ >= maxAttempts) {
throw e; // 超过最大重试次数,抛出异常
}

try {
Thread.sleep(period); // 等待后重试
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw e;
}
}

@Override
public Retryer clone() {
return new CustomRetryer(maxAttempts, period);
}
}

错误解码器

自定义错误响应的处理逻辑:

public class CustomErrorDecoder implements ErrorDecoder {

@Override
public Exception decode(String methodKey, Response response) {
int status = response.status();

switch (status) {
case 400:
return new BadRequestException("请求参数错误");
case 401:
return new UnauthorizedException("未授权");
case 404:
return new NotFoundException("资源不存在");
case 429:
return new RateLimitException("请求过于频繁");
case 500:
case 502:
case 503:
// 服务端错误,触发重试
return new RetryableException(
status,
"服务暂时不可用",
HttpMethod.POST,
null,
response.request()
);
default:
return new FeignException.UnexpectedErrorException(
"未知错误: " + status
);
}
}
}

注册错误解码器:

@Bean
public ErrorDecoder errorDecoder() {
return new CustomErrorDecoder();
}

HTTP 客户端配置

OpenFeign 支持多种 HTTP 客户端实现。

Apache HttpClient 5

添加依赖:

<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-hc5</artifactId>
</dependency>

配置:

spring:
cloud:
openfeign:
httpclient:
hc5:
enabled: true
max-connections: 200 # 最大连接数
max-connections-per-route: 50 # 每个路由的最大连接数
connection-timeout: 5000
socket-timeout: 10000

OkHttp

添加依赖:

<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>

配置:

spring:
cloud:
openfeign:
okhttp:
enabled: true

自定义 OkHttp 配置:

@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(10, 5, TimeUnit.MINUTES))
.build();
}

压缩配置

启用请求/响应压缩:

spring:
cloud:
openfeign:
compression:
request:
enabled: true
mime-types: text/xml,application/xml,application/json # 压缩的 MIME 类型
min-request-size: 2048 # 最小压缩大小(字节)
response:
enabled: true
注意

如果使用 OkHttp,由于其内置了透明压缩,启用压缩配置可能会导致冲突。

GZIP 压缩

对于大数据量的请求和响应,启用 GZIP 压缩可以显著减少网络传输时间:

public class FeignConfig {

@Bean
public RequestInterceptor gzipInterceptor() {
return template -> {
template.header("Accept-Encoding", "gzip");
template.header("Content-Encoding", "gzip");
};
}
}

配置优先级

当多种配置方式同时存在时,优先级如下:

  1. YAML 中的客户端配置
  2. Java 配置类中的 Bean 定义
  3. YAML 中的全局配置(default
  4. 默认配置

可以通过配置改变优先级:

spring:
cloud:
openfeign:
client:
default-to-properties: false # Java 配置优先于 YAML 配置

配置刷新

启用配置动态刷新:

spring:
cloud:
openfeign:
client:
refresh-enabled: true

启用后,可以通过 /actuator/refresh 端点动态刷新配置:

curl -X POST http://localhost:8080/actuator/refresh
注意

不要在 @FeignClient 接口上使用 @RefreshScope 注解,这会导致问题。

小结

本章详细介绍了 OpenFeign 的配置机制:

配置项说明默认值
connectTimeout连接超时10 秒
readTimeout读取超时60 秒
loggerLevel日志级别NONE
retryer重试策略NEVER_RETRY
errorDecoder错误解码器默认解码器
requestInterceptors请求拦截器

下一章将学习请求拦截器,掌握如何统一处理请求和响应。