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

.NET Lambda调用SQS DeleteMessageAsync无响应 无法删除队列消息

.NET Lambda调用SQS DeleteMessageAsync挂起无响应问题排查

问题现象

基于.NET框架开发的SQS标准队列触发Lambda函数,预期消息处理完成后主动删除队列消息避免重复消费,核心实现代码如下:

using Amazon.Lambda.Core;
using Amazon.Lambda.SQSEvents;
using Amazon.Runtime;
using Amazon.SQS;
using Amazon.SQS.Model;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace AWSLambda1;

public class Function
{
    public Function()
    {
    }

    public async Task FunctionHandler(SQSEvent evnt, ILambdaContext context)
    {
        foreach (var message in evnt.Records)
        {
            if (ProcessMessage(message))
                await DeleteMessage(message, context);
        }

    }

    private static bool ProcessMessage(SQSEvent.SQSMessage message)
    {
        Console.WriteLine($"\nMessage body of {message.MessageId}:");
        Console.WriteLine($"{message.Body}");
        return true;
    }

    private static async Task DeleteMessage(SQSEvent.SQSMessage message, ILambdaContext context)
    {
        var sqsClient = new AmazonSQSClient();
        var qUrl = "https://sqs.eu-north-1.amazonaws.com/XXXXXXXXXX/TestQueue";

        try
        {
            context.Logger.LogInformation($"\nDeleting message {message.MessageId} from queue...");
            context.Logger.LogInformation($"\nReceipt Handle: {message.ReceiptHandle}");

            var deleteReq = new DeleteMessageRequest
            {
                QueueUrl = qUrl,
                ReceiptHandle = message.ReceiptHandle
            };

            var deleteResp = await sqsClient.DeleteMessageAsync(deleteReq);

            // This block of code is never reached
            context.Logger.LogInformation($"\nDeleted message {message.MessageId} from queue...");
            context.Logger.LogInformation($"\nDeleted message with status {deleteResp.HttpStatusCode}");
        }
        catch (Exception e)
        {
            context.Logger.LogInformation($"\nEXCEPTION ON DELETE MESSAGE {e.Message} from queue...");
            throw;
        }
    }
}

代码参考官方示例编写,排查过程中未在日志中发现任何错误输出,日志样例如下:

2022-06-28T22:30:19.441+03:00   START RequestId: c86729c3-5df9-57b0-8b46-72f6050fae56 Version: $LATEST
2022-06-28T22:30:19.805+03:00   2022-06-28T19:30:19.748Z c86729c3-5df9-57b0-8b46-72f6050fae56 info
2022-06-28T22:30:19.805+03:00   Message body of 9a99b479-66f5-4740-afb5-6dc9693e5907:
2022-06-28T22:30:19.805+03:00   2022-06-28T19:30:19.805Z c86729c3-5df9-57b0-8b46-72f6050fae56 info test
2022-06-28T22:30:20.425+03:00   2022-06-28T19:30:20.425Z c86729c3-5df9-57b0-8b46-72f6050fae56 info
2022-06-28T22:30:20.425+03:00   Deleting message 9a99b479-66f5-4740-afb5-6dc9693e5907 from queue...
2022-06-28T22:30:20.425+03:00   2022-06-28T19:30:20.425Z c86729c3-5df9-57b0-8b46-72f6050fae56 info
2022-06-28T22:30:20.425+03:00   Receipt Handle: AQEBH/vZmNFFir4oshRJxMGtOAAuu+KcboUqRnFWNCseksSAT+ShxslAaRJP1BoDk6L+3iSvMoxdRUcspHCfY40hZumCZvJnuD8U0IEOG6jwRMdORjP7oTpdsRoV/ZloAQL5tJzlK/jRHRWlsTPr1n1IpkS4sXgPnD8fxrW0OiG3ARX/N/ii1RsWLMZnc4tgYFpGicuKdT0/EzdUonenTwDut4KHQVZWbu4nisqc6y2IyyhZwOXyfzLoc7Jk+DeCulRZPpcPRUk1qeUoLExc3fSnFukMtizm8i2to82OaKqkc27ZFyXRGQzEChL5ed/Z1RRPTUlSt/qzgjye2IXhvU2u6piZ/kFpV4v7+3tQ2Ts1oMCs5M+HiONS1wVlqlpGzAunSDmpaXtZF+7HAk97LeYPPg==
2022-06-28T22:30:49.451+03:00   END RequestId: c86729c3-5df9-57b0-8b46-72f6050fae56

从日志可以看到,DeleteMessageAsync调用后的两行日志始终不会执行,请求等待约30秒后直接结束,无异常抛出、无删除成功响应返回,消息无法正常删除。

排查方向与根因定位

从日志时间差判断:打印完Receipt Handle的时间点是22:30:20,请求结束时间是22:30:49,间隔恰好29秒,和Lambda默认30秒超时阈值吻合,说明请求全程卡在网络等待阶段,没有收到任何服务端响应(包括错误响应),因此既不会执行后续成功逻辑,也不会进入catch块,最终被Lambda运行时强制终止。按优先级从高到低排查以下问题即可解决:

  • 网络连通性问题(90%概率为该原因)
    首先检查Lambda的VPC配置:如果Lambda部署在自定义VPC的私有子网内,默认没有公网访问能力,无法连通SQS的公网服务端点,会导致TCP请求直接挂起。两种修复方案二选一:给私有子网绑定NAT网关提供公网出口,或者在对应VPC内创建SQS服务的VPC端点,通过内网访问SQS。
    同时检查Lambda绑定的安全组出站规则,确认没有拦截到SQS服务443端口的出站流量。
  • SQS客户端配置问题
    不要在每次执行DeleteMessage时重复实例化AmazonSQSClient,将客户端初始化逻辑移到Function构造函数中做单例复用,避免每次调用重复建立TCP连接引发连接异常。
    初始化客户端时显式指定和队列一致的eu-north-1区域,不要依赖SDK的默认区域自动探测,Lambda环境下自动探测逻辑偶尔会因元数据服务访问超时导致请求挂起。同时给客户端配置显式的请求超时,避免请求无限挂住无法抛出异常,修正后的初始化代码如下:
    private readonly AmazonSQSClient _sqsClient;
    private const string QUrl = "https://sqs.eu-north-1.amazonaws.com/XXXXXXXXXX/TestQueue";
    
    public Function()
    {
        var sqsConfig = new AmazonSQSConfig
        {
            RegionEndpoint = RegionEndpoint.EUNorth1,
            Timeout = TimeSpan.FromSeconds(5)
        };
        _sqsClient = new AmazonSQSClient(sqsConfig);
    }
    
    后续删除消息时直接复用构造函数中初始化的_sqsClient即可。
  • 权限配置校验
    确认Lambda执行角色绑定的权限策略包含sqs:DeleteMessage操作,资源字段正确填写目标SQS队列的ARN,避免权限不足导致的请求失败。
  • 超时配置校验
    不要使用Lambda默认3秒超时配置,至少将Lambda超时时间设置为10秒以上,给SDK的重试逻辑预留足够时间。

注:SQS作为Lambda事件源时,只要函数执行未抛出异常,Lambda服务会自动批量删除处理成功的消息,无需手动调用DeleteMessage接口,可减少自定义代码的异常风险。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 15:24:26