您可以在动态计时器上触发 AWS Lambda 吗?
Can you trigger an AWS Lambda on a dynamic timer?
有没有办法在动态计时器上触发 AWS Lambda?目前,我正在利用预定事件来触发 lambda,但这是一个设定的计时器。有没有办法动态设置从 Lambda 内部触发 Lambda 的时间?
这里的想法是,此 Lambda 会进行特定检查并执行代码以了解下一步应该 运行 的时间(因为我只希望此 lambda 在需要时 运行)。我想 1) 确定下一次需要 运行 和 2) 从 Lambda 代码中设置时间。
我看到有很多资源可用于触发 Lambda 函数(SNS、Kinesis 等),但我似乎找不到动态启动的好方法。
您可以在特定时间为 运行 创建 CloudWatch 规则。 CloudWatch 规则可以是 运行 周期性的,也可以使用类似 cron 的语法,让您指定单个 运行 时间。不过,您稍后可能需要清理它们。
您可以继续按计划执行 lambda,但在 DynamoDB 或 S3 等数据存储中保留一个值,告诉 lambda 下一步应该运行。
lambda 将继续定期执行,但您可以控制它何时真正执行预期的操作。这里有计费方面的考虑(lambda 将继续在后台消耗最少的资源)但希望事情不会变得太失控。可能比尝试从同一个 lambda 中管理触发器更简单。
这可以通过设置 CloudWatch 事件规则来触发您的 Lambda 函数来实现。每次调用您的 Lambda 函数时,该函数都需要确定其下一个 运行 时间并适当修改事件规则。
var AWS = require("aws-sdk");
exports.handler = function(event, context) {
var cloudwatchevents = new AWS.CloudWatchEvents();
var intervals = Array(3, 5, 7);
var nextInterval = intervals[Math.floor(Math.random()*intervals.length)];
var currentTime = new Date().getTime(); // UTC Time
var nextTime = dateAdd(currentTime, "minute", nextInterval);
var nextMinutes = nextTime.getMinutes();
var nextHours = nextTime.getHours();
// =================================
// DO YOUR WORK HERE
// =================================
var scheduleExpression = "cron(" + nextMinutes + " " + nextHours + " * * ? *)";
var params = {
Name: "YOUR CLOUDWATCH EVENT RULE NAME",
ScheduleExpression: scheduleExpression
};
cloudwatchevents.putRule(params, function(err, data) {
if (err) {
console.log(err, err.stack);
}
else {
console.log(data);
}
})
};
var dateAdd = function(date, interval, units) {
var ret = new Date(date); // don't change original date
switch(interval.toLowerCase()) {
case 'year' : ret.setFullYear(ret.getFullYear() + units); break;
case 'quarter': ret.setMonth(ret.getMonth() + 3*units); break;
case 'month' : ret.setMonth(ret.getMonth() + units); break;
case 'week' : ret.setDate(ret.getDate() + 7*units); break;
case 'day' : ret.setDate(ret.getDate() + units); break;
case 'hour' : ret.setTime(ret.getTime() + units*3600000); break;
case 'minute' : ret.setTime(ret.getTime() + units*60000); break;
case 'second' : ret.setTime(ret.getTime() + units*1000); break;
default : ret = undefined; break;
}
return ret;
}
你应该能够用你自己的调度逻辑交换我的随机决定,并插入你需要的任何工作来代替我的评论。
您需要用事件规则的名称替换我的代码段中的 "YOUR CLOUDWATCH EVENT RULE NAME"。
博客的好问题:AWS Lambda Functions That Dynamically Schedule Their Next Runtime
现在无需使用步进函数进行轮询即可完成此操作。您可以在 AWS 上找到更多信息,但基本上您会为使用 Wait
状态和 TimestampPath
字段的步进函数定义一个状态机。您的状态机最终可能看起来像
{
"SartAt": "WaitState",
"States": {
"WaitState": {
"Type": "Wait",
"TimestampPath": "$.timestamp",
"Next": "ExecuteLambda"
},
"ExecuteLambda": {
"Type": "Task",
"Resource": "lambda-arn",
"End": true,
"Retry": [
{ ... },
...
]
}
}
假设您使用的是 Node,则可以使用以下代码调用 step 函数:
const AWS = require('aws-sdk');
const stepFunctions = new AWS.StepFunctions();
await stepFunctions.startExecution({
stateMachineArn: process.env.STATE_MACHINE_ARN,
name: "unique-name",
input: JSON.stringify({
timestamp: (new Date(/*Date you want to start execution*/)).toISOString(),
// Any extra context you want to pass to the step function.
}),
}).promise();
有没有办法在动态计时器上触发 AWS Lambda?目前,我正在利用预定事件来触发 lambda,但这是一个设定的计时器。有没有办法动态设置从 Lambda 内部触发 Lambda 的时间?
这里的想法是,此 Lambda 会进行特定检查并执行代码以了解下一步应该 运行 的时间(因为我只希望此 lambda 在需要时 运行)。我想 1) 确定下一次需要 运行 和 2) 从 Lambda 代码中设置时间。
我看到有很多资源可用于触发 Lambda 函数(SNS、Kinesis 等),但我似乎找不到动态启动的好方法。
您可以在特定时间为 运行 创建 CloudWatch 规则。 CloudWatch 规则可以是 运行 周期性的,也可以使用类似 cron 的语法,让您指定单个 运行 时间。不过,您稍后可能需要清理它们。
您可以继续按计划执行 lambda,但在 DynamoDB 或 S3 等数据存储中保留一个值,告诉 lambda 下一步应该运行。
lambda 将继续定期执行,但您可以控制它何时真正执行预期的操作。这里有计费方面的考虑(lambda 将继续在后台消耗最少的资源)但希望事情不会变得太失控。可能比尝试从同一个 lambda 中管理触发器更简单。
这可以通过设置 CloudWatch 事件规则来触发您的 Lambda 函数来实现。每次调用您的 Lambda 函数时,该函数都需要确定其下一个 运行 时间并适当修改事件规则。
var AWS = require("aws-sdk");
exports.handler = function(event, context) {
var cloudwatchevents = new AWS.CloudWatchEvents();
var intervals = Array(3, 5, 7);
var nextInterval = intervals[Math.floor(Math.random()*intervals.length)];
var currentTime = new Date().getTime(); // UTC Time
var nextTime = dateAdd(currentTime, "minute", nextInterval);
var nextMinutes = nextTime.getMinutes();
var nextHours = nextTime.getHours();
// =================================
// DO YOUR WORK HERE
// =================================
var scheduleExpression = "cron(" + nextMinutes + " " + nextHours + " * * ? *)";
var params = {
Name: "YOUR CLOUDWATCH EVENT RULE NAME",
ScheduleExpression: scheduleExpression
};
cloudwatchevents.putRule(params, function(err, data) {
if (err) {
console.log(err, err.stack);
}
else {
console.log(data);
}
})
};
var dateAdd = function(date, interval, units) {
var ret = new Date(date); // don't change original date
switch(interval.toLowerCase()) {
case 'year' : ret.setFullYear(ret.getFullYear() + units); break;
case 'quarter': ret.setMonth(ret.getMonth() + 3*units); break;
case 'month' : ret.setMonth(ret.getMonth() + units); break;
case 'week' : ret.setDate(ret.getDate() + 7*units); break;
case 'day' : ret.setDate(ret.getDate() + units); break;
case 'hour' : ret.setTime(ret.getTime() + units*3600000); break;
case 'minute' : ret.setTime(ret.getTime() + units*60000); break;
case 'second' : ret.setTime(ret.getTime() + units*1000); break;
default : ret = undefined; break;
}
return ret;
}
你应该能够用你自己的调度逻辑交换我的随机决定,并插入你需要的任何工作来代替我的评论。
您需要用事件规则的名称替换我的代码段中的 "YOUR CLOUDWATCH EVENT RULE NAME"。
博客的好问题:AWS Lambda Functions That Dynamically Schedule Their Next Runtime
现在无需使用步进函数进行轮询即可完成此操作。您可以在 AWS 上找到更多信息,但基本上您会为使用 Wait
状态和 TimestampPath
字段的步进函数定义一个状态机。您的状态机最终可能看起来像
{
"SartAt": "WaitState",
"States": {
"WaitState": {
"Type": "Wait",
"TimestampPath": "$.timestamp",
"Next": "ExecuteLambda"
},
"ExecuteLambda": {
"Type": "Task",
"Resource": "lambda-arn",
"End": true,
"Retry": [
{ ... },
...
]
}
}
假设您使用的是 Node,则可以使用以下代码调用 step 函数:
const AWS = require('aws-sdk');
const stepFunctions = new AWS.StepFunctions();
await stepFunctions.startExecution({
stateMachineArn: process.env.STATE_MACHINE_ARN,
name: "unique-name",
input: JSON.stringify({
timestamp: (new Date(/*Date you want to start execution*/)).toISOString(),
// Any extra context you want to pass to the step function.
}),
}).promise();