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

SpringBoot+Apache Camel SFTP路由重投递失效问题求助

解决Apache Camel SFTP连接异常重投递失效问题

问题根源

你的问题核心在于:SFTP消费者在**poll阶段(执行ls列文件操作)**抛出的异常,是由Camel的PollingConsumerPollStrategy处理的,而非路由中配置的onException重投递机制。默认的RemoteFilePollingConsumerPollStrategy在处理异常时,rollback方法会返回false,这会告诉调度器直接放弃本次poll的重试,直接进入异常处理器,导致你配置的maximumRedeliveries完全不生效。

解决方案

要实现poll阶段的重试,需要自定义PollStrategy,针对特定的临时异常返回true,让调度器重新执行poll操作;同时调整onException配置,确保重试耗尽后再触发自定义错误处理。

1. 自定义SFTP重试PollStrategy

import org.apache.camel.Exchange;
import org.apache.camel.component.file.remote.RemoteFilePollingConsumerPollStrategy;

import java.io.IOException;

public class SftpRetryPollStrategy extends RemoteFilePollingConsumerPollStrategy {

    private int maxRetries = 3;
    private int retryCount = 0;

    @Override
    public boolean rollback(Exchange exchange, Throwable cause) throws Exception {
        // 拆解异常链,定位底层IOException
        Throwable rootCause = getRootCause(cause);
        if (rootCause instanceof IOException && "input stream closed".equals(rootCause.getMessage())) {
            if (retryCount < maxRetries) {
                retryCount++;
                // 返回true,通知调度器重试本次poll
                return true;
            } else {
                // 重试耗尽,重置计数后返回false,触发后续异常处理
                retryCount = 0;
                return false;
            }
        }
        // 其他异常沿用默认处理逻辑
        return super.rollback(exchange, cause);
    }

    @Override
    public void commit(Exchange exchange) throws Exception {
        // poll成功后重置重试计数
        retryCount = 0;
        super.commit(exchange);
    }

    private Throwable getRootCause(Throwable cause) {
        while (cause.getCause() != null) {
            cause = cause.getCause();
        }
        return cause;
    }

    // 配置重试次数的setter
    public void setMaxRetries(int maxRetries) {
        this.maxRetries = maxRetries;
    }
}

2. 注册自定义PollStrategy到Spring容器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class CamelConfig {

    @Bean
    public SftpRetryPollStrategy sftpRetryPollStrategy() {
        SftpRetryPollStrategy strategy = new SftpRetryPollStrategy();
        strategy.setMaxRetries(3); // 设置目标重试次数
        return strategy;
    }
}

3. 修改SFTP端点配置,绑定自定义PollStrategy

在路由的SFTP端点中添加pollStrategy参数,指向自定义的bean实例:

@Override
public void configure() {
    onException(IOException.class)
        .logHandled(true)
        .log("SFTP重试耗尽,触发IOException处理")
        .bean(consumerExceptionHandler, "handleIOException")
        .handled(true)
        .end();

    onException(Exception.class)
        .logHandled(true)
        .bean(consumerExceptionHandler, "handleException")
        .handled(true)
        .end();

    from("sftp://user@host:22/directory?password=secret&disconnect=true&pollStrategy=#sftpRetryPollStrategy")
        .routeId("sftpRouteWithRetry")
        .log("Starting SFTP route to fetch files")
        .to(myQueue)
        .log("File downloaded successfully to /local/directory")
        .end();
}

4. 调整重试间隔(可选)

如果需要控制两次poll重试的间隔,可以通过SFTP端点的delay参数调整基础调度间隔;若需要在重试时动态延长间隔,可在自定义PollStrategy的rollback方法中添加Thread.sleep()逻辑。

关键说明

  • poll阶段与路由阶段的区别:Camel的onException重投递针对的是路由处理阶段的异常(比如to(myQueue)抛出的异常),而SFTP的ls操作属于消费者poll阶段的异常,由PollStrategy独立控制。
  • 自定义PollStrategy的核心逻辑:通过rollback方法返回true,告诉调度器重新执行poll操作,直到重试耗尽后返回false,触发onException的自定义错误处理逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 14:37:14