现有Spring Batch项目中发布SNS Topic的最优实现方案咨询
方案评估与实现建议
方案1:复用现有ItemWriter实现
该方案改造成本最低,且不会因为数据量过大引发内存溢出问题,尤其适合你提到的「超长对象列表」场景:
- 你当前的
afterStep方法已经完成了CSV生成并写入S3的逻辑,直接注入AWS S3客户端读取s3://output.csv的内容即可调用SNS发布,AWS S3当前全区域默认支持读写强一致性,不会出现写完读不到的问题。 - 注意SNS单次发布消息的payload上限为256KB:如果你的CSV文件体积超过该阈值,不要直接把CSV内容作为消息体发送,改为在邮件正文中插入S3文件的预签名下载链接即可。
方案2:全量对象暂存后生成CSV发送
该方案适合CSV体积较小、不想额外调用S3读接口的场景,对象存储可选两种实现:
单节点作业可选成员变量存储
如果你的Spring Batch作业是单节点运行、没有开启分片处理,直接给Writer类新增成员变量存储全量对象即可,实现最简单:
@StepScope // 必须加该注解,避免多次作业运行出现数据残留 class StudentWriter implements ItemWriter<Student> { @Autowired ResourceLoader resourceLoader List<Student> allStudents = [] // 新增成员变量存储全量对象 WritableResource resource OutputStreamWriter writer CSVPrinter csvPrinter void prepare() { this.resource = this.resourceLoader("s3://output.csv") this.writer = new OutputStreamWriter(this.resource.outputStream) this.csvPrinter = new CSVPrinter(this.writer, CSVFormat.DEFAULT) } @Override void write(List<? extends Student> items) throws Exception { this.csvPrinter.with { printer -> items.each { it -> printer.printRecord(it.id, it.name, it.subjects) } } allStudents.addAll(items) // 每批次写入时追加对象到成员变量 } @AfterStep void afterStep() { this.csvPrinter.close() // 直接用allStudents生成CSV字符串,调用SNS发布即可 } }
多节点作业可选Step执行上下文存储
如果作业是多节点分片运行,可以把每批次对象追加到Spring Batch的ExecutionContext中,数据会持久化到Spring Batch的元数据表中,适合对象总量不超过几千条的场景,数据量过大会导致元数据表膨胀、序列化性能下降。
方案3:新增Lambda实现
该方案仅适合两种场景:CSV体积超过SNS阈值且不想在Spring Batch中处理预签名链接逻辑、发送逻辑需要和批处理作业解耦后续频繁修改规则。其余场景下确实属于资源浪费,没有必要采用。
内容的提问来源于stack exchange,提问作者p4rt2020
相关产品推荐
相关产品推荐

