You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Integration:区分连接失败与错误响应码,仅重试连接失败

区分连接失败与HTTP错误码,仅对连接失败应用重试

问题的核心在于默认的SimpleRetryPolicy会对所有运行时异常进行重试,而连接失败抛出的ResourceAccessException和HTTP错误码抛出的RestClientResponseException都属于运行时异常,所以才会被一起重试。我们需要通过自定义重试策略来区分这两类异常,只对连接相关的异常触发重试逻辑。

步骤1:识别异常类型

首先明确两种场景对应的异常:

  • 连接失败:通常会抛出ResourceAccessException,其根源(getCause())一般是ConnectException(无法建立连接)或SocketTimeoutException(连接超时)。
  • HTTP错误码(如400、500):会抛出RestClientResponseException的子类,比如HttpClientErrorException(4xx)或HttpServerErrorException(5xx)。

步骤2:自定义重试策略

我们可以使用ExceptionClassifierRetryPolicy来实现异常分类,针对不同异常类型应用不同的重试规则:

@Bean("retryAdvice")
public RequestHandlerRetryAdvice maspRetryAdvice() {
    RequestHandlerRetryAdvice retryAdvice = new RequestHandlerRetryAdvice();
    RetryTemplate retryTemplate = new RetryTemplate();

    // 配置退避策略(和你原来的逻辑一致)
    FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
    backOffPolicy.setBackOffPeriod(interval);
    retryTemplate.setBackOffPolicy(backOffPolicy);

    // 创建分类重试策略
    ExceptionClassifierRetryPolicy classifierRetryPolicy = new ExceptionClassifierRetryPolicy();

    // 1. 连接失败时的重试策略:允许重试nRetry次
    SimpleRetryPolicy connectionRetryPolicy = new SimpleRetryPolicy();
    connectionRetryPolicy.setMaxAttempts(nRetry);

    // 2. HTTP错误码时的策略:不重试(仅执行1次)
    SimpleRetryPolicy noRetryPolicy = new SimpleRetryPolicy();
    noRetryPolicy.setMaxAttempts(1);

    // 配置异常分类逻辑
    classifierRetryPolicy.setExceptionClassifier(throwable -> {
        // 判断是否是连接相关异常
        if (throwable instanceof ResourceAccessException) {
            Throwable rootCause = throwable.getCause();
            if (rootCause instanceof ConnectException || rootCause instanceof SocketTimeoutException) {
                return connectionRetryPolicy;
            }
        }
        // 判断是否是HTTP响应错误异常
        if (throwable instanceof RestClientResponseException) {
            return noRetryPolicy;
        }
        // 其他异常默认不重试(可根据需求调整)
        return noRetryPolicy;
    });

    retryTemplate.setRetryPolicy(classifierRetryPolicy);

    // 恢复回调逻辑(保持你原来的配置)
    ErrorMessageSendingRecoverer recover = new ErrorMessageSendingRecoverer(aggregatorChannel());
    retryAdvice.setRecoveryCallback(recover);
    retryAdvice.setRetryTemplate(retryTemplate);

    return retryAdvice;
}

替代方案:使用SimpleRetryPolicy的异常映射

如果你不需要太精细的异常根源判断,也可以直接通过SimpleRetryPolicy的retryableExceptions来配置:

@Bean("retryAdvice")
public RequestHandlerRetryAdvice maspRetryAdvice() {
    RequestHandlerRetryAdvice retryAdvice = new RequestHandlerRetryAdvice();
    RetryTemplate retryTemplate = new RetryTemplate();

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

    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
    Map<Class<? extends Throwable>, Boolean> exceptionMap = new HashMap<>();
    // 允许重试连接相关异常
    exceptionMap.put(ResourceAccessException.class, true);
    // 禁止重试HTTP响应错误异常
    exceptionMap.put(RestClientResponseException.class, false);
    retryPolicy.setRetryableExceptions(exceptionMap);
    retryPolicy.setMaxAttempts(nRetry);

    retryTemplate.setRetryPolicy(retryPolicy);

    ErrorMessageSendingRecoverer recover = new ErrorMessageSendingRecoverer(aggregatorChannel());
    retryAdvice.setRecoveryCallback(recover);
    retryAdvice.setRetryTemplate(retryTemplate);

    return retryAdvice;
}

关键说明

  • 第一种方案更灵活,可以深入判断异常的根源,避免误重试其他类型的ResourceAccessException(比如读取响应超时但连接已建立的情况)。
  • 确保你的Http.outboundGateway配置会正确抛出HTTP错误码异常:默认情况下,DefaultResponseErrorHandler会在非2xx状态码时抛出RestClientResponseException,如果自定义了errorHandler,需要保证异常被正确抛出。

内容的提问来源于stack exchange,提问作者Ramy Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:49:19