EKS部署中Apache Camel pollEnrich加载大文件触发堆内存溢出问题求助
问题分析与解决方案
核心原因
从错误日志可以明确:Camel的AWS2 S3组件默认会把S3文件的全部内容读取到内存的ByteArrayOutputStream中。处理1GB以上文件时,单个文件就几乎占满2GB堆内存,再加上10个线程并行处理,必然触发内存溢出。ECS环境之前能正常运行,大概率是当时JVM堆配置更高或线程并发数更低,未触发阈值。
解决方法
核心思路是避免把整个文件加载到内存,改用流处理直接写入本地文件系统,具体步骤如下:
1. 配置S3组件启用流模式
修改pollEnrich的S3端点,添加useBodyAsInputStream=true参数,让消息体返回InputStream而非byte数组:
.log(LoggingLevel.INFO, "Before enriching") .pollEnrich() .simple("aws2-s3://arn:aws:s3:::bucketname?useBodyAsInputStream=true") .cacheSize(-1) .aggregationStrategy(new HeadersCopyAggregationStrategy())
2. 直接将流写入本地文件
在路由中新增处理步骤,把InputStream直接写入本地文件,避免在内存中缓存整个流:
.log(LoggingLevel.INFO, "Before enriching") .pollEnrich() .simple("aws2-s3://arn:aws:s3:::bucketname?useBodyAsInputStream=true") .cacheSize(-1) .aggregationStrategy(new HeadersCopyAggregationStrategy()) // 新增:将流写入指定本地目录,文件名沿用S3对象键 .to("file:/your/local/dir?fileName=${header.CamelAwsS3Key}") .log(LoggingLevel.INFO, "Finished Enriching File")
3. 可选:调整JVM与并发配置
- 若需保留并发数,可适当提升JVM堆内存(比如调整到4GB以上),但这只是临时缓解方案,流处理才是根本解决方式。
- 降低线程数(比如从10调整到2-3),减少同时加载的大文件数量,同样属于临时缓解手段。
4. 验证聚合策略兼容性
确保HeadersCopyAggregationStrategy不会尝试读取整个InputStream(比如不要调用IOUtils.toByteArray这类方法),保持流的原样传递给后续处理步骤。
补充说明
Camel的pollEnrich默认会缓存整个消息体,加上S3组件默认全量加载文件到内存,这种组合对大文件场景极不友好。改用流模式后,文件内容会以流的形式逐步写入本地,内存占用仅维持在流缓冲区的大小,而非整个文件体积。
内容的提问来源于stack exchange,提问作者user1097437
相关产品推荐
相关产品推荐

