Apache Camel动态SFTP URI处理文件引发OutOfMemory问题求助
Apache Camel SFTP组件引发OutOfMemory异常求助
我们的应用长期抛出OutOfMemory异常,最初怀疑是集合使用效率低导致的,深入分析应用和堆转储后,定位到问题由Apache Camel引发。
应用场景是每日从SFTP拉取PGP加密文件,解密后处理数据并插入数据库。目前怀疑是Camel依赖的JSch缓冲区未释放内存,导致内存持续泄漏。
以下是我们的Camel路由示例:
from("sftpUrl"+dynamic_fileName+".pgp"+"&noop=true&delay=5m&stepwise=false") .routeId("id") .process(isNotAllprocessed) .unmarshal().pgp(somekey,user,pwd) .unmarshal().string() .process(writeToDBProcessor) .log("Done");
我们已经尝试过启用streamcaching()和重构处理器,但问题仍未解决。Stack Overflow上相关解决方案多针对JMS场景,未找到适配本问题的案例,特此求助:
- 是否有人遇到过此类SFTP+PGP场景的内存泄漏问题?
- 麻烦给出问题成因及可行的规避方法。
问题成因及解决方法
可能的成因
- JSch通道/缓冲区未正确关闭:当使用
noop=true时,Camel的SFTP组件可能不会主动关闭JSch的ChannelSftp实例,其内部的输入流缓冲区会持续占用堆内存,长期运行后堆积引发OOM。 - 全量加载文件到内存:
unmarshal().string()会把解密后的整个文件内容加载为内存字符串,若处理大文件,这本身就会占用大量内存,和JSch的内存泄漏问题叠加后更易触发OOM。 - SFTP会话复用导致资源残留:Camel默认会复用SFTP会话,闲置会话关联的缓冲区资源若未及时回收,也会逐渐占用内存。
规避方法
替换字符串反序列化为流式处理
去掉unmarshal().string(),直接将解密后的InputStream传递给writeToDBProcessor,在处理器中分片读取流并插入数据库,避免一次性加载整个大文件到内存。显式关闭JSch通道
在路由中添加完成回调,确保每次处理后关闭SFTP通道:from("sftpUrl"+dynamic_fileName+".pgp"+"&noop=true&delay=5m&stepwise=false") .routeId("id") .process(isNotAllprocessed) .unmarshal().pgp(somekey,user,pwd) .process(writeToDBProcessor) .log("Done") .onCompletion() .process(exchange -> { ChannelSftp channel = exchange.getIn().getHeader(SftpConstants.SFTP_CHANNEL, ChannelSftp.class); if (channel != null && channel.isConnected()) { try { channel.disconnect(); } catch (JSchException e) { // 添加日志记录异常 } } });调整JSch缓冲区及会话配置
在SFTP URL中添加参数,限制缓冲区大小并设置会话闲置超时:from("sftpUrl"+dynamic_fileName+".pgp"+"&noop=true&delay=5m&stepwise=false&bufferSize=8192&sessionMaxIdleTime=30000")bufferSize=8192:限制JSch每次读取的缓冲区大小,减少单文件处理的内存占用sessionMaxIdleTime=30000:设置会话闲置30秒后自动过期,释放关联资源
启用PGP流式解密
如果使用的Camel版本支持,配置PGP组件启用流式解密,避免将整个明文加载到内存:.unmarshal().pgp(somekey,user,pwd).streaming(true)
内容的提问来源于stack exchange,提问作者B.War
相关产品推荐
相关产品推荐

