📖 主要讲解 - 重试机制 Fallback 机制
🗣️-简介
OpenFeign 是一个声明式的 HTTP 客户端,它简化了 REST API 的调用过程。但在复杂的生产环境中,高级配置变得至关重要,以下是使用OpenFeign 高级配置的主要原因其中之一比如:
提升调用性能和稳定性:
- 重试机制💫 :配置请求失败时的重试策略,提高系统在短暂网络故障中的容错能力。
- Fallback 机制 🚀:远程服务不可用时提供备用逻辑,确保系统的健壮性和可用性。
🧠-学习目的
这篇文章我们将探讨OpenFeign 高级配置🔥 ,我们希望达成以下具体的目标:
- ✅重试机制:理解如果请求失败,怎么使用重试机制预设的策略重新尝试发送请求 。
- ✅Fallback机制:理解远程服务不可用时如何提供备用逻辑。
💫-重试机制
1️⃣-原理介绍
OpenFeign 客户端向远程服务发送请求时,如果请求失败(例如由于网络连接中断、超时、服务端返回错误状态码等原因),重试机制会根据预设的策略重新尝试发送请求。
2️⃣-核心作用
- 容错保障:在网络波动、服务短暂不可用(如超时、5xx错误)时,通过自动重试提升系统可用性。
- 异常触发:默认针对
IOException(如连接超时、SocketException)触发重试,非所有异常(如4xx错误通常不重试)。
3️⃣-默认重试策略
重试器:Retryer.Default。
- 最大重试次数:3次(首次请求 + 3次重试 = 最多4次调用)。
- 退避策略:间隔时间逐步递增(避免雪崩效应),公式近似为
间隔 = 100ms * (1 + 重试次数)。
4️⃣-适用场景示例
- 电商系统案例:订单服务调用库存服务时,若因网络抖动导致超时,OpenFeign自动重试,避免业务中断。
- 关键场景:读操作(如查询库存)、幂等写操作(如GET/PUT);非幂等操作(如POST)需谨慎启用。
5️⃣-自定义重试器
在实际应用中,有时默认的重试策略可能无法满足业务需求,这时就需要自定义重试器。定义自定义重试器可以通过实现Retryer接口或继承RetryTemplate类来实现。example如下:
5.1-实现 Retryer 接口
import feign.Retryer;
public class CustomRetryer implements Retryer {
private int maxAttempts = 5; // 最大重试次数
private long period = 1000; // 初始重试间隔时间,单位毫秒
private long maxPeriod = 5000; // 最大重试间隔时间,单位毫秒
private int attempt = 1;
@Override
public void continueOrPropagate(RetryableException e) {
if (attempt++ >= maxAttempts) {
throw e;
}
long interval;
if (e.retryAfter() != null) {
interval = e.retryAfter().getTime() - System.currentTimeMillis();
if (interval > maxPeriod) {
interval = maxPeriod;
}
if (interval < 0) {
return;
}
} else {
interval = nextMaxInterval();
}
try {
Thread.sleep(interval);
} catch (InterruptedException ignored) {
Thread.currentThread().interrupt();
throw e;
}
}
private long nextMaxInterval() {
long interval = (long) (period * Math.pow(1.5, attempt - 1));
return interval > maxPeriod? maxPeriod : interval;
}
@Override
public Retryer clone() {
return new CustomRetryer();
}
}
在上述代码中,CustomRetryer实现了Retryer接口,并重写了continueOrPropagate和clone方法。continueOrPropagate方法中定义了重试的逻辑,根据当前重试次数和最大重试次数进行判断,如果超过最大重试次数则抛出异常;否则,根据retryAfter或自定义的算法计算重试间隔时间,并让线程休眠相应时间。nextMaxInterval方法用于计算下一次重试的间隔时间,这里采用了指数增长的方式,避免重试过于频繁。
5.2-继承 RetryTemplate 类
import org.springframework.retry.RetryCallback;
import org.springframework.retry.RetryContext;
import org.springframework.retry.support.RetryTemplate;
public class CustomRetryTemplate extends RetryTemplate {
public CustomRetryTemplate() {
// 设置重试策略
setRetryPolicy(new SimpleRetryPolicy(5, 1000)); // 重试5次,每次间隔1秒
}
@Override
public <T> T execute(RetryCallback<T, Exception> retryCallback) throws Exception {
return super.execute(retryCallback, new DefaultRecoveryCallback<>());
}
@Override
public <T> T execute(RetryCallback<T, Exception> retryCallback, RetryContext context) throws Exception {
return super.execute(retryCallback, context);
}
@Override
public <T> T execute(RetryCallback<T, Exception> retryCallback, RetryContext context, RecoveryCallback<T> recoveryCallback) throws Exception {
return super.execute(retryCallback, context, recoveryCallback);
}
}
在这个示例中,CustomRetryTemplate继承自RetryTemplate类,并在构造函数中设置了自定义的重试策略,这里设置为重试 5 次,每次间隔 1 秒。同时,根据需要重写了execute方法,以满足特定的业务需求。
5.3-注册自定义重试器
在 Spring 配置类中注册自定义重试器。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignRetryConfig {
@Bean
public Retryer customRetryer() {
return new CustomRetryer();
}
}
5.4-使用自定义重试器
在@FeignClient注解的配置类中,将自定义的重试器添加到配置中
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = "stock", configuration = FeignRetryConfig.class)
public interface StockFeignClient {
@GetMapping("/stock")
String getStock();
}
通过以上步骤,就可以实现自定义的重试机制,以适应不同的业务场景和需求。
🚑-Fallback 机制
1️⃣-Fallback原理
在 OpenFeign 中,Fallback 机制用于在远程服务不可用时提供备用逻辑,确保系统的健壮性和可用性。
2️⃣-核心作用
- 服务降级:当远程服务调用失败(如超时、熔断、异常)时,提供备用逻辑(Fallback),避免级联故障,保障系统可用性。
- 用户体验:返回默认值、缓存数据或友好提示,而非直接抛出异常。
3️⃣-实现方式
定义 Fallback 类的方法是创建一个实现 Feign 客户端接口的类,并使用@Component注解将其注册为 Spring Bean。这个类将包含在远程服务调用失败时执行的备用逻辑。
假设我们有一个StockFeignClient接口用于调用库存服务:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "stock")
public interface StockFeignClient {
@GetMapping("/stock")
String getStock();
}
对应的 Fallback 类可以这样定义:
import org.springframework.stereotype.Component;
@Component
public class StockFeignClientFallback implements StockFeignClient {
@Override
public String getStock() {
// 备用逻辑,例如返回一个默认值或错误提示信息
return "Stock service is unavailable";
}
}
在上述代码中,StockFeignClientFallback类实现了StockFeignClient接口,并实现了其中的getStock方法。在getStock方法中,定义了备用逻辑,当远程的库存服务不可用时,将返回 "Stock service is unavailable",而不是抛出异常,从而保证系统的其他部分能够继续正常运行。
4️⃣-配置 Fallback
配置 Fallback 是使 Fallback 机制生效的重要环节,主要有两种方式,即在@FeignClient注解中指定fallback属性和使用fallbackFactory属性。
指定 fallback 属性
在@FeignClient注解中使用fallback属性,直接指向 Fallback 类。
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "stock", fallback = StockFeignClientFallback.class)
public interface StockFeignClient {
@GetMapping("/stock")
String getStock();
}
通过上述配置,当调用StockFeignClient接口的方法失败时,会自动调用StockFeignClientFallback类中对应的方法,执行备用逻辑。
使用 fallbackFactory 属性
如果需要访问导致 Fallback 触发的异常原因,可以使用fallbackFactory属性。首先定义一个 Fallback 工厂类:
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class StockFeignClientFallbackFactory implements FallbackFactory<StockFeignClient> {
@Override
public StockFeignClient create(Throwable cause) {
return new StockFeignClient() {
@Override
public String getStock() {
// 根据异常原因执行不同的备用逻辑
return "Error occurred: " + cause.getMessage();
}
};
}
}
然后在@FeignClient注解中指定fallbackFactory属性:
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(name = "stock", fallbackFactory = StockFeignClientFallbackFactory.class)
public interface StockFeignClient {
@GetMapping("/stock")
String getStock();
}
在这种方式下,当远程服务调用失败时,会调用StockFeignClientFallbackFactory类的create方法创建一个 Fallback 实例,并传入导致失败的异常对象,从而可以根据异常原因执行不同的备用逻辑。
Fallback 优先级
配置文件 > 自定义
在项目中,Fallback 的配置可能存在多种方式,包括通过配置属性和@Configuration类定义 Fallback,此时就涉及到 Fallback 的优先级问题。
默认情况下,配置属性的优先级高于@Configuration类定义的 Fallback。也就是说,如果在配置文件中设置了 Fallback,同时又在@Configuration类中定义了 Fallback,那么配置文件中的 Fallback 将生效。
如果想要改变优先级,使@Configuration类优先,可以在配置文件中设置:
spring.cloud.openfeign.client.default-to-properties: false
通过上述配置,@Configuration类中定义的 Fallback 将具有更高的优先级
🎉-总结
| 机制 | 重试(Retry) | Fallback(降级) |
|---|---|---|
| 核心目标 |
提高请求成功率(自动重试失败请求) |
保障系统可用性(失败时提供备用逻辑) |
| 触发条件 |
网络超时、IO异常、5xx错误等可重试异常 |
熔断触发、所有异常(包括重试耗尽后的失败) |
| 执行阶段 |
调用过程中(尚未返回给客户端) |
调用失败后(已确认无法成功) |
| 默认行为 |
默认重试3次(可配置) |
需显式定义Fallback类或工厂 |
| 适用场景 |
临时性故障(如网络抖动、服务短暂不可用) |
依赖服务长期不可用、必须返回兜底结果 |
| 资源影响 |
可能增加服务端负载(多次重试) |
无额外请求压力(直接本地逻辑) |
| 配置关键 |
|
|
| 典型实现 |
|
|


8019

被折叠的 条评论
为什么被折叠?



