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

Java 17 Lambda写入JSON到S3时CloudWatch指标丢失问题

问题描述

我用Java 17开发了一个AWS Lambda函数,触发条件是当JSON文件上传到指定S3存储桶时执行。上传的JSON包含DynamoDB、RDS等AWS资源名称,Lambda会拉取这些资源的CloudWatch指标,整合到新的JSON对象中,最后将这个JSON写入文件并上传到另一个S3桶。

目前遇到的诡异问题:

  • 执行写入+上传S3的操作时,最终生成的JSON完全没有指标数据
  • 但只要注释掉写入和上传的代码,控制台打印的JSON就包含完整的指标数据
  • 试过两种上传方式:临时文件写入后上传、直接字节流上传,结果完全一致
  • 进一步排查发现:仅注释掉s3.putObject这一行,打印的JSON就有指标;取消注释,指标就丢失,而且指标拉取的逻辑本身是正常的。
可能的原因及解决办法

1. JSON序列化时机或线程安全问题

如果你的JSON对象使用了非线程安全的集合(比如普通HashMap)存储指标,或者在调用s3.putObject时才进行序列化,可能因为IO操作的并发特性导致数据未被正确写入。

解决步骤:

  • 先完成JSON序列化,生成字节数组或字符串,再执行上传操作,避免上传时才序列化:
// 提前完成序列化,确保数据已固化
ObjectMapper objectMapper = new ObjectMapper();
byte[] jsonData = objectMapper.writeValueAsBytes(yourMetricJsonObj);

// 再上传到S3
s3.putObject(PutObjectRequest.builder()
        .bucket("target-bucket-name")
        .key("output.json")
        .contentType("application/json")
        .build(),
        RequestBody.fromBytes(jsonData));
  • 确保存储指标的集合是线程安全的,比如用Collections.synchronizedMap()包装,或者在序列化前拷贝到新的不可变对象中。

2. Lambda执行生命周期导致的资源中断

Lambda的执行环境可能因为IO操作耗时,提前回收了某些资源,比如后台异步的指标拉取任务未完成就被终止。

解决步骤:

  • 确认所有指标拉取操作都是同步执行的,如果用了CompletableFuture这类异步工具,必须调用join()或get()等待所有任务完成后再处理上传。
  • 在序列化前加一次日志打印,确认JSON对象里已经包含指标数据,再执行上传。

3. 上传前意外修改了JSON对象

检查代码中是否有逻辑在调用s3.putObject前,清空或修改了JSON对象的指标字段,比如某些清理代码误删了数据。

解决步骤:

  • 在上传前做一次数据校验,比如打印JSON字符串,或者将其写入Lambda临时目录(/tmp)查看内容,确认数据完整性。
  • 排查是否有全局变量或共享对象被意外修改,尽量使用局部变量存储生成的JSON对象。

4. S3上传的元数据或权限问题

虽然概率低,但权限不足或元数据错误也可能导致文件内容异常。

解决步骤:

  • 检查Lambda执行角色是否拥有目标S3桶的s3:PutObject权限。
  • 上传时显式指定Content-Type: application/json,避免S3默认编码导致内容解析异常(如上述代码示例)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 03:42:50