Spring retry 如何使用Spring Retry包装耗尽重试时的异常

Spring retry 如何使用Spring Retry包装耗尽重试时的异常,spring-retry,Spring Retry,上下文: 我正在使用spring重试来重试restTemplate调用 restTemplate调用是从kafka侦听器调用的。 kafka侦听器还配置为在出错时重试(如果在该过程中引发任何异常,而不仅仅是restTemplate调用) 目标: 我想防止kafka在错误来自已耗尽的重试模板时重试 实际行为: 当retryTemplate用尽所有重试次数时,将引发原始异常。从而阻止我识别retryTemplate是否重试了错误 期望的行为: 当retryTemplate用尽所有重试次数时,将原始异

上下文:

我正在使用spring重试来重试restTemplate调用

restTemplate调用是从kafka侦听器调用的。 kafka侦听器还配置为在出错时重试(如果在该过程中引发任何异常,而不仅仅是restTemplate调用)

目标:

我想防止kafka在错误来自已耗尽的重试模板时重试

实际行为:

当retryTemplate用尽所有重试次数时,将引发原始异常。从而阻止我识别retryTemplate是否重试了错误

期望的行为:

当retryTemplate用尽所有重试次数时,将原始异常包装在RetryExtustedException中,这将允许我将其从kafka重试中列入黑名单

问题:

我怎么能做这样的事

谢谢

编辑

RetryTemplate配置:

RetryTemplate retryTemplate = new RetryTemplate();

FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
backOffPolicy.setBackOffPeriod(1000);
retryTemplate.setBackOffPolicy(backOffPolicy);

Map<Class<? extends Throwable>, Boolean> retryableExceptions = new HashMap<>();
retryableExceptions.put(FunctionalException.class, false);
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(3, retryableExceptions, true, true);
retryTemplate.setRetryPolicy(retryPolicy);

retryTemplate.setThrowLastExceptionOnExhausted(false);
RetryTemplate RetryTemplate=new RetryTemplate();
FixedBackOffPolicy backOffPolicy=新的FixedBackOffPolicy();
退避政策。退避期(1000);
retryTemplate.setBackOffPolicy(backOffPolicy);

映射只需使用配置为将
retryExhustedException
分类为不可重试的
simpleRetryPolicy
配置侦听器重试模板

由于容器将所有侦听器异常包装在
ListenerExecutionFailedException
中,因此请确保将
TraverseCaues
属性设置为true

/**
 * Create a {@link SimpleRetryPolicy} with the specified number of retry
 * attempts. If traverseCauses is true, the exception causes will be traversed until
 * a match is found. The default value indicates whether to retry or not for exceptions
 * (or super classes) are not found in the map.
 *
 * @param maxAttempts the maximum number of attempts
 * @param retryableExceptions the map of exceptions that are retryable based on the
 * map value (true/false).
 * @param traverseCauses is this clause traversable
 * @param defaultValue the default action.
 */
public SimpleRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
        boolean traverseCauses, boolean defaultValue) {

我已经将带有TraverseCaues的SimpleRetryPolicy配置为true。但这是抛出原始异常,然后将其封装在LEFE中。我想要的是触发RetryExhaustedException,而不是原始异常。如果(thrownException instanceof RetryExhustedException)在ErrorHandler中,您需要编辑问题并显示代码,那么我可以这样做-容器无法从链的顶部剥离您的
RetryExhustedException
-它对侦听器异常一无所知。我想你是从你的恢复回拨中抛出的。如果没有恢复回调,模板将抛出一个
ExhustedRetryException
包装原始异常,除非您已将
ThrowLasteExceptionNext
设置为true,这将导致您描述的行为。编辑了我的问题,但是throwlastexceptionnexhausted并没有被使用,因为RetryTemplate类中的状态为null——得到了;很抱歉在这种情况下,您应该在
execute()
中添加一个恢复回调,并将包装器扔到那里。我用一个例子编辑了我的答案。请注意,如果需要,您可以使用
context.setAttribute(…)将任意信息从
RetryCallback
传递到
RecoveryCallback
@KafkaListener
public void onMessage(ConsumerRecord<String, String> record) {
    retryTemplate.execute((args) -> {
        throw new RuntimeException("Should be catched by ErrorHandler to prevent rollback");
    }
    throw new RuntimeException("Should be retried by afterRollbackProcessor");
}
/**
 * Create a {@link SimpleRetryPolicy} with the specified number of retry
 * attempts. If traverseCauses is true, the exception causes will be traversed until
 * a match is found. The default value indicates whether to retry or not for exceptions
 * (or super classes) are not found in the map.
 *
 * @param maxAttempts the maximum number of attempts
 * @param retryableExceptions the map of exceptions that are retryable based on the
 * map value (true/false).
 * @param traverseCauses is this clause traversable
 * @param defaultValue the default action.
 */
public SimpleRetryPolicy(int maxAttempts, Map<Class<? extends Throwable>, Boolean> retryableExceptions,
        boolean traverseCauses, boolean defaultValue) {
template.execute((args) -> {...}, (context) -> throw new Blah(context.getLastThrowable()));