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

Lambda集成DynamoDB与SNS超时求助:执行成功但反复重试

问题根源分析

从你的日志和代码来看,核心问题是无限递归调用getmsg函数,加上异步操作的回调时机错误,导致Lambda函数一直在循环执行DynamoDB查询和SNS发送,直到触发10秒超时限制。

具体问题点拆解:

  • 无限递归:你的getmsg函数在DynamoDB成功/失败的回调里,又再次调用了getmsg,形成了无限循环。日志里重复出现的Dynamo Success和push sent就是明证——函数一直在反复执行相同的操作,停不下来。
  • Callback调用过早:你在handler里直接同步调用了callback(null, {statusCode:200}),这会让Lambda认为函数已经执行完成,但实际上DynamoDB和SNS的异步操作还在后台运行,加上递归的无限循环,事件队列一直被占满,最终导致超时。
  • context.callbackWaitsForEmptyEventLoop设置位置错误:这个参数需要在handler的最开始设置,而且因为无限递归的存在,即使设置正确,事件循环也永远不会清空,所以这个配置起不到作用。
  • 变量作用域混乱:MESSAGE_ID的定义和传递逻辑混乱,函数参数和内部变量重名,导致逻辑出错。
修复方案

下面是修正后的代码,解决了上述所有问题:

exports.handler = function (event, context, callback) {
    // 首先设置这个参数,放在handler最开头
    context.callbackWaitsForEmptyEventLoop = false;
    
    var AWS = require('aws-sdk');
    var doc = require('dynamodb-doc');
    var dynamodb = new doc.DynamoDB();
    var sns = new AWS.SNS({ 
        region:'eu-west-1', 
        maxRetries: 0 
    });

    var params = {
        TableName : 'abcmsg',
        ProjectionExpression: 'Message',
        Key : { "ind" : "ABC10" }
    };

    // 重构getmsg为单次执行的异步函数,去掉递归
    function getmsg() {
        dynamodb.getItem(params, function (err, data) {
            if (err) {
                console.log('ERROR: Dynamo Failed:', err);
                // 出错时调用callback返回错误
                return callback(err);
            } 
            
            console.log('Dynamo Success: ' + JSON.stringify(data, null, ' '));
            const MESSAGE_ID = data['Item'].Message;
            console.log('data', MESSAGE_ID);

            // 发送SNS通知,在SNS回调里结束Lambda函数
            sns.publish({
                Message: MESSAGE_ID,
                Subject:"Test Message",
                TopicArn:"arn:aws:sns:eu-west-1:0123456789012:Lambda"
            }, function (err, snsData) {
                if (err) {
                    console.log(err.stack);
                    return callback(err);
                }
                console.log('push sent');
                // 所有异步操作完成后,调用callback结束函数
                callback(null, { "statusCode": 200 });
            });
        });
    }

    // 调用一次getmsg,不再递归
    getmsg();
};
关键修复点说明
  • 移除无限递归:getmsg现在只执行一次DynamoDB查询,查询完成后执行SNS发送,不再自我调用。
  • 正确的Callback时机:只有当SNS发送完成(成功或失败)后,才调用callback,让Lambda知道函数真正执行完毕。
  • 调整context.callbackWaitsForEmptyEventLoop位置:放在handler最开始,确保Lambda在callback调用后不会等待事件循环清空(不过现在我们的逻辑里所有异步操作都在callback前完成,这个配置其实可以去掉,但保留也没问题)。
  • 清理变量作用域:统一MESSAGE_ID的定义,避免变量名冲突。

这样修改后,函数会执行一次DynamoDB查询,发送一次SNS通知,然后正常结束,不会再出现超时和重复执行的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:57:54