.NET 6 Lambda通过SQS接收S3事件时消息体为空的问题
问题原因与解决方法
你遇到的核心问题是:SQS接收到的消息是经过SNS封装后的结构,而非原始的S3事件JSON。直接按S3事件格式解析自然拿不到数据,而改用S3Event类时,是跳过了SNS/SQS的中间层,直接让Lambda接收S3的原始事件触发,所以能正常解析。
具体原因
当你通过S3→SNS→SQS→Lambda的链路传递事件时,SQS中的消息体并非直接的S3事件内容,而是SNS的消息结构。典型的SNS消息格式大致如下:
{ "Type": "Notification", "MessageId": "xxxx-xxxx-xxxx", "TopicArn": "arn:aws:sns:region:account:topic-name", "Message": "{\"Records\":[{\"s3\":{...}}]}", // 这里才是原始的S3事件JSON "Timestamp": "2024-xx-xxTxx:xx:xx.xxxZ", "SignatureVersion": "1", // 其他SNS相关字段 }
你之前的代码直接把整个消息体当成S3事件解析,自然找不到Records字段,导致消息体看似“为空”或解析失败。
修正后的代码示例
你需要先解析SNS的消息结构,取出Message字段后,再解析成S3事件:
方法1:使用AWS Lambda SDK提供的SNSEvent类(推荐)
using Amazon.Lambda.SQSEvents; using Amazon.Lambda.SNSEvents; using Newtonsoft.Json; public async Task FunctionHandler(SQSEvent sqsEvent, ILambdaContext context) { foreach (var sqsRecord in sqsEvent.Records) { // 先解析SNS消息 var snsEvent = JsonConvert.DeserializeObject<SNSEvent>(sqsRecord.Body); var s3EventJson = snsEvent.Records[0].Sns.Message; // 再解析S3事件 var s3Event = JsonConvert.DeserializeObject<Amazon.Lambda.S3Events.S3Event>(s3EventJson); var s3Record = s3Event.Records[0]; var bucketName = s3Record.S3.Bucket.Name; var objectKey = s3Record.S3.Object.Key; // 后续处理逻辑 } }
方法2:手动用JObject解析
using Amazon.Lambda.SQSEvents; using Newtonsoft.Json.Linq; public async Task FunctionHandler(SQSEvent sqsEvent, ILambdaContext context) { var sqsRecord = sqsEvent.Records[0]; var snsMessage = JObject.Parse(sqsRecord.Body); // 取出SNS包裹的原始S3事件消息 var s3EventJson = snsMessage["Message"].ToString(); var s3Event = JObject.Parse(s3EventJson); var bucketName = s3Event["Records"][0]["s3"]["bucket"]["name"].ToString(); var objectKey = s3Event["Records"][0]["s3"]["object"]["key"].ToString(); // 后续处理逻辑 }
为什么用S3Event类直接触发能正常工作
当你把Lambda的触发器直接设为S3事件时,Lambda接收的是原始的S3事件JSON,没有经过SNS的封装,所以可以直接用Amazon.Lambda.S3Events.S3Event类反序列化,直接获取record.S3.Bucket.Name等字段。
内容的提问来源于stack exchange,提问作者CPK_2011
相关产品推荐
相关产品推荐

