配置详解
OpenFeign 提供了灵活的配置机制,支持全局配置和客户端级别配置。本章将深入讲解各种配置选项及其使用场景。
配置方式概览
OpenFeign 支持三种配置方式:
- Java 配置类:使用
@Configuration定义配置 Bean - YAML 配置文件:在
application.yml中配置 - 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 全局配置
使用 @EnableFeignClients 的 defaultConfiguration 属性:
@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 客户端配置
针对特定客户端进行配置,客户端名称对应 @FeignClient 的 name 或 value 属性:
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,或者将其放在 @ComponentScan 扫描范围之外。
核心配置项详解
超时配置
OpenFeign 有两个超时参数:
- connectTimeout:建立连接的超时时间
- readTimeout:从建立连接到接收响应的超时时间
spring:
cloud:
openfeign:
client:
config:
default:
connectTimeout: 5000 # 5 秒连接超时
readTimeout: 30000 # 30 秒读取超时
超时时间设置建议:
| 场景 | connectTimeout | readTimeout |
|---|---|---|
| 普通业务接口 | 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");
};
}
}
配置优先级
当多种配置方式同时存在时,优先级如下:
- YAML 中的客户端配置
- Java 配置类中的 Bean 定义
- YAML 中的全局配置(
default) - 默认配置
可以通过配置改变优先级:
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 | 请求拦截器 | 空 |
下一章将学习请求拦截器,掌握如何统一处理请求和响应。