从 lambda 调用 DynamoDB 停止,甚至没有错误

call to DynamoDB from a lambda stops dead, not even an error

我正在测试一些代码。在本地有效。当我把它放在 lambda 中时,它停止了!

index.js

const AWS = require("aws-sdk");
const MyHandler = require("./handler.js");

// Initialise DynamoDB client outside of lambda for re-use
if (typeof docClient === 'undefined') {
    var docClient = new AWS.DynamoDB.DocumentClient({region: "eu-west-1"})
}

exports.handler = async (event, context, callback) => {
    context.dynamoDbClient = docClient;

    await MyHandler.processEvent(event, context);
}

handler.js

processEvent = (event, context) => {
    console.log("Message received");
    var params = {
        TableName: "TestTable",
        Item: {"test": "test"}
    };
    console.log("Inserting into dynamoDB");
    try {
        return context.dynamoDbClient.put(params, (error, data) => {
            if (error) {
                console.log("Error: Unable to insert DynamoDB: " + error);
            } else {
                console.log("Inserted into dynamoDB");
            }
        });
    } catch (err) {
        console.log("Error inserting to dynamoDB: " + e);
    }
};

在 AWS 日志中,在 Message received 之后我除了 END RequestId:... 之外什么也没有得到。

您正在使用 await 和同步函数 processEvent - 这将立即解决;等不及了。

一旦您的处理程序 returns,Lambda 将 'kill' 未解决的承诺,或者在您的情况下是回调。无论您在本地测试什么,都可能不会这样做,因此尽管您的处理程序函数已返回,但回调会在该环境中执行(推测)。

您的问题是您错误地将回调与 Promises 混合在一起。 AWS SDK 为几乎所有调用公开了一个 promise 选项,因此我建议使用它而不是自己编写:

processEvent = (event, context) => {
    var params = {
        TableName: "TestTable",
        Item: {"test": "test"}
    };
    return context.dynamoDbClient.put(params).promise()
};

可能导致此问题的另一个问题:如果您将 lambda 附加到 VPC/Subnet,则必须确保子网具有 网关端点(到dynamodb服务)并且有一条路由将流量定向到该端点。

否则对 dynamoDB 的 lambda 请求将停止,因为 dynamo 永远不会收到查询请求。

在这个问题上关注 AWS 文档: https://docs.amazonaws.cn/en_us/vpc/latest/privatelink/vpc-endpoints-ddb.html

如果您使用 Terraform 部署 AWS 服务,您需要这样的东西:

resource "aws_vpc_endpoint" "dynamodb_endpoint" {
  vpc_id       = data.your_vpc.id
  service_name = "com.amazonaws.${data.aws_region.current.name}.dynamodb"
  route_table_ids   = [for r in data.your_route_tables : r.id]
}