使用spring-integration合并文件时应用无限运行问题
Spring Integration SFTP文件合并无限运行问题排查与修复
问题现象
使用Spring Integration的SftpRemoteFileTemplate合并SFTP服务器上的多个文件到目标文件file3.txt时,出现以下异常情况:
- 应用启动后无限运行,无法正常结束
- 目标文件仅包含第一个待合并文件的内容
- 日志输出到
Authentication succeeded (publickey)后无任何后续日志
原代码问题分析
@EventListener(ApplicationReadyEvent.class) public void mergeFiles() { for (String file : fileNamesList){ try { sftpRemoteFileTemplate.execute((SessionCallbackWithoutResult<ChannelSftp.LsEntry>) session -> { session.append(session.readRaw("path/to/input/"+file), "path/to/output/file3.txt"); }); } catch (Exception e) { log.error("Could not send file per FTP: " + e); } finally { sftpRemoteFileTemplate.getSession().close(); log.info("closing FTP session "); } } }
- 手动关闭会话导致阻塞:
SftpRemoteFileTemplate.execute()方法会自动负责会话的获取、使用和释放,手动调用getSession().close()会破坏会话池管理逻辑,后续循环中尝试获取会话时会陷入无限等待。 - 输入流未关闭:
session.readRaw()返回的InputStream未关闭,会持续占用SFTP会话资源,导致后续操作无法正常执行。 - 循环内重复建立会话:每次循环都调用
execute(),重复建立SFTP连接,既降低效率,又加剧了会话管理的混乱。
修复后的代码
@EventListener(ApplicationReadyEvent.class) public void mergeFiles() { sftpRemoteFileTemplate.execute((SessionCallbackWithoutResult<ChannelSftp.LsEntry>) session -> { for (String file : fileNamesList) { try (InputStream inputStream = session.readRaw("path/to/input/" + file)) { session.append(inputStream, "path/to/output/file3.txt"); log.info("已合并文件: {}", file); } catch (Exception e) { log.error("合并文件{}失败: {}", file, e.getMessage(), e); } } log.info("所有文件合并完成"); }); }
修复说明
- 复用SFTP会话:将文件循环逻辑放在
execute()方法内部,全程复用同一个SFTP会话,避免重复建立连接。 - 自动关闭输入流:使用try-with-resources语法,确保
readRaw()返回的输入流在使用后自动关闭,及时释放资源。 - 移除手动会话管理:依赖
SftpRemoteFileTemplate的自动会话管理机制,避免手动操作会话导致的异常。 - 增强日志输出:添加文件合并成功/失败的明细日志,便于跟踪执行进度和排查问题。
内容的提问来源于stack exchange,提问作者Chaitanya Pandit
相关产品推荐
相关产品推荐

