从 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]
}
我正在测试一些代码。在本地有效。当我把它放在 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]
}