Spring 在 lambda 函数中重试似乎不起作用
Spring Retry in a lambda function doesn't seem to work
我有一个使用 Spring Boot 构建的 lambda 函数,它对每秒可以接受 10 个请求的服务进行 REST 调用。在这 10 个请求之后,我得到了 403。
事实证明,尝试找到一种在此限制条件下工作的方法很困难。
目前我的代码看起来像
@Slf4j
@UtilityClass
public class HttpUtil {
private final RestTemplate restTemplate = new RestTemplate();
@Retryable(maxAttempts = 60, backoff = @Backoff(delay = 10000, multiplier = 2))
public ResponseEntity<String> sendPostRequest(@NonNull final MultiValueMap<String, Object> data, @NonNull final String url) {
final HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(data, new HttpHeaders());
return restTemplate.postForEntity(url, request, String.class);
}
}
但是,如果我关闭它并检查日志,我可以看到 403 异常被一遍又一遍地抛出,并且似乎没有 "backing off" 期间发生。
我试图扩展 RetryListenerSupport
以添加更多日志记录,以便我可以看到实际的退避期,但似乎已被忽略,尽管已加载。这是否需要与 RetryTemplate` 一起使用而不仅仅是注释?
不然是不是我的注释明显有问题?还是有更简单的方法来实现我的方法的“每秒 10 个请求上限”?
编辑:
配置class
@EnableRetry
@Configuration
public class RetryTemplateConfig {
@Bean
public RetryTemplate retryTemplate() {
final RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.registerListener(new DefaultListenerSupport());
return retryTemplate;
}
}
还有一个非常简单的监听器
@Slf4j
public class DefaultListenerSupport extends RetryListenerSupport {
@Override
public <T, E extends Throwable> void close(final RetryContext context,
final RetryCallback<T, E> callback, final Throwable throwable) {
log.info("onClose {}", throwable.getMessage());
super.close(context, callback, throwable);
}
@Override
public <T, E extends Throwable> void onError(final RetryContext context,
final RetryCallback<T, E> callback, final Throwable throwable) {
log.info("onError {}", throwable.getMessage());
super.onError(context, callback, throwable);
}
@Override
public <T, E extends Throwable> boolean open(final RetryContext context,
final RetryCallback<T, E> callback) {
log.info("onOpen");
return super.open(context, callback);
}
}
干杯
使用@Retryable
注解的class需要是Springbean,否则需要直接使用RetryTemplate
而不是注解。
如果你不想让你的 class 成为一个豆子,你可以这样做:
private static final RetryTemplate retryTemplate = new RetryTemplate();
static {
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(60);
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setMultiplier(2);
backOffPolicy.setInitialInterval(10000);
retryTemplate.setRetryPolicy(retryPolicy);
retryTemplate.setBackOffPolicy(backOffPolicy);
}
private void doSomething() {
retryTemplate.execute(retryContext -> {
return restTemplate.postForEntity(url, request, String.class);
});
}
我有一个使用 Spring Boot 构建的 lambda 函数,它对每秒可以接受 10 个请求的服务进行 REST 调用。在这 10 个请求之后,我得到了 403。
事实证明,尝试找到一种在此限制条件下工作的方法很困难。
目前我的代码看起来像
@Slf4j
@UtilityClass
public class HttpUtil {
private final RestTemplate restTemplate = new RestTemplate();
@Retryable(maxAttempts = 60, backoff = @Backoff(delay = 10000, multiplier = 2))
public ResponseEntity<String> sendPostRequest(@NonNull final MultiValueMap<String, Object> data, @NonNull final String url) {
final HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(data, new HttpHeaders());
return restTemplate.postForEntity(url, request, String.class);
}
}
但是,如果我关闭它并检查日志,我可以看到 403 异常被一遍又一遍地抛出,并且似乎没有 "backing off" 期间发生。
我试图扩展 RetryListenerSupport
以添加更多日志记录,以便我可以看到实际的退避期,但似乎已被忽略,尽管已加载。这是否需要与 RetryTemplate` 一起使用而不仅仅是注释?
不然是不是我的注释明显有问题?还是有更简单的方法来实现我的方法的“每秒 10 个请求上限”?
编辑:
配置class
@EnableRetry
@Configuration
public class RetryTemplateConfig {
@Bean
public RetryTemplate retryTemplate() {
final RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.registerListener(new DefaultListenerSupport());
return retryTemplate;
}
}
还有一个非常简单的监听器
@Slf4j
public class DefaultListenerSupport extends RetryListenerSupport {
@Override
public <T, E extends Throwable> void close(final RetryContext context,
final RetryCallback<T, E> callback, final Throwable throwable) {
log.info("onClose {}", throwable.getMessage());
super.close(context, callback, throwable);
}
@Override
public <T, E extends Throwable> void onError(final RetryContext context,
final RetryCallback<T, E> callback, final Throwable throwable) {
log.info("onError {}", throwable.getMessage());
super.onError(context, callback, throwable);
}
@Override
public <T, E extends Throwable> boolean open(final RetryContext context,
final RetryCallback<T, E> callback) {
log.info("onOpen");
return super.open(context, callback);
}
}
干杯
使用@Retryable
注解的class需要是Springbean,否则需要直接使用RetryTemplate
而不是注解。
如果你不想让你的 class 成为一个豆子,你可以这样做:
private static final RetryTemplate retryTemplate = new RetryTemplate();
static {
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
retryPolicy.setMaxAttempts(60);
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setMultiplier(2);
backOffPolicy.setInitialInterval(10000);
retryTemplate.setRetryPolicy(retryPolicy);
retryTemplate.setBackOffPolicy(backOffPolicy);
}
private void doSomething() {
retryTemplate.execute(retryContext -> {
return restTemplate.postForEntity(url, request, String.class);
});
}