【问题标题】:How to Send SNS Message from Lambda every 24 Hours?如何每 24 小时从 Lambda 发送 SNS 消息?
【发布时间】:2019-09-28 18:39:20
【问题描述】:

我是 Lambda 的新手,我正在尝试编写一个函数,该函数将每 24 小时通过 SNS 发送一封具有流量的电子邮件。此 Lambda 函数由 IoT 规则触发,没有 24 小时限制,收件箱将充满电子邮件。在 CloudWatch 中,即使 email_sent 标志等于 1,看起来也正在发送电子邮件。所以这让我觉得我的括号和括号结构不正确?有人看到这段代码有什么问题吗?


var email_sent = 0;  //Flag to determine if the email has been sent in the last 24 hours
var starttime = new Date();  //Date & time when the script starts running

....

exports.handler = (event, context, callback) => {
 console.log('Start time.', starttime);
 console.log('Email Sent Flag.', email_sent);
 console.log('Received event:', event.my_volume, ' mL Volume');  //Fluid volume
 var miliseconds = new Date() - starttime;  //Calculate the time that has passed
 console.log('Miliseconds.', miliseconds);
 console.log(miliseconds/1000 + " Seconds.");
 if (miliseconds => 86,400,000) {    //Has 24 hours passed?
     email_sent = 0;   //set the email flag back to zero if the time has passed
 }
 // create/get topic
 if (email_sent == 0) {  //if the email flag is not set, setup topic and send the email
 createTopic('aws-iot-button-sns-topic', (err, topicArn) => {
     if (err) {
         return callback(err);
     }
     console.log(`Publishing to topic ${topicArn}`);
     // publish message
     const params = {
         Message: `The fluid level is low on your system: ${event.my_volume} mL.`,
         Subject: `Low Fluid Level Alert - Knight`,
         TopicArn: topicArn,
     };

     // result will go to function callback
     SNS.publish(params, callback);
     console.log('SNS Published.');
     email_sent = 1;  // after email is sent, reset the flag
     starttime = new Date();  // reset the starttime after the email is sent
 }
 );
} 
};

谢谢,

史蒂夫

【问题讨论】:

  • 能否更详细地描述您的要求?是“每天一次,如果 IoT 显示低于 X 的值,则向 Amazon SNS 主题发送消息”?假设某些东西正在更新 IoT 中的值(可能是设备影子)是否正确?当前触发 Lambda 函数的是什么——物联网是否触发了它?告诉我们有关您的设置的更多信息将有助于我们为您提供建议。
  • 我正在测量与 AWS IoT Core 服务通信的设备中的液位。如果液位低于阈值,我想使用触发 Lambda 函数的 IoT 规则发送警报。因为设备影子每隔几秒钟更新一次,所以它会在收件箱中充斥着警报。所以 AWS 支持说我需要使用 Lambda 函数来发送电子邮件并将其执行限制为每 24 小时一次。所以是的,每天一次,如果 IoT 显示的值低于 X,则向 Amazon SNS 主题发送一条消息。
  • 您真的想每 24 小时发送一次警报,还是只发送一次警报就足够了(当液位低于阈值时)?我问这个是因为它可能值得将指标发布到 Amazon CloudWatch,然后使用警报触发 Amazon SNS 通知。另一方面,如果您确实希望每 24 小时发出一次警报,那么 AWS Lambda 函数将需要跟踪时间。
  • 我只想在液位低于阈值时发送警报,因为这是有人去手动重新填充液体容器的信号。一旦液位低于阈值,警报需要限制为每 24 小时一次。否则,每次更新设备影子时,收件箱都会收到警报。
  • 是的,但是如果级别下降到阈值以下并且发送了一条消息,并且级别仍然低于阈值,则需要再次发送通知,或者一条消息足够并且存在不需要重复发送消息吗? (如果一条消息就足够了,那么可以选择 CloudWatch。如果需要重复发送,则需要对解决方案应用额外的逻辑和历史跟踪。)

标签: node.js aws-lambda amazon-sns


【解决方案1】:

所以我认为有两件事应该以不同的方式完成。

首先,你有这个:

createTopic('aws-iot-button-sns-topic', (err, topicArn) => {

现在您的函数正在创建不必要的主题而不删除它们,这是一个问题。您应该改为在外部创建 SNS 主题并在此处通过使用 Lambda 环境变量或硬编码 SNS 主题 arn 来引用它。或者,首先检查具有该名称的主题是否已经存在,如果存在则不要创建它。

其次,Lambda 的运行时间不会超过 900 seconds (15 minutes),因此无法检查脚本是否已运行超过 24 小时。

您应该做的是创建一个CloudWatch event trigger that runs every 24 hours using cron。这样,您的 lambda 将每 24 小时运行一次(或您配置的任何事件),并且在代码中您只需发送一次消息。这样就无需检查现在是什么时间或您已经发送了多少,因为您知道事件触发只发生一次,因此您的消息会被发送一次,您的 Lambda 会立即结束其执行。

Lambda 的本质是它们是短暂且无状态的,因此请相应地设计您的服务:)

编辑:评论后,我更了解用例......在这种情况下,Lambda 由 IoT 执行,我会亲自将之前的执行时间存储在 SSM 参数存储或 DynamoDB 中,然后每当 Lambda执行时,我会获取值,检查是否已过 24 小时,如果已过,则发送 SNS。您必须这样做,因为 Lambda 不会知道上次执行时间是什么时候(并确保仅在成功的 SNS 发布调用上更新上次执行时间,这样您就可以确定当天发送了一条消息)

【讨论】:

  • 你说的很有道理,Deiv。用例虽然有点复杂。让我澄清一下。如果设备影子值低于阈值,则仅应由 IoT 规则调用 Lambda 函数。所以规则开始执行 Lambda,但最终 CloudWatch 可以将其执行限制为每 24 小时一次?
【解决方案2】:

这是另一种方法...

  • 将温度推送到 Amazon CloudWatch 指标(见下文)
  • 创建 Amazon CloudWatch 警报以在温度低于给定阈值时触发
  • 警报可以向Amazon SNS 主题发送消息
  • 人们可以订阅 SNS 主题以在发送消息时接收电子邮件

这只会在指标低于阈值时发送一条消息。不需要 Lambda(也许)。

我不完全确定如何将 IoT 指标发送到 CloudWatch(我对 IoT 不太熟悉)。这可能是相关的:Real-time metrics with AWS IoT Analytics and Amazon CloudWatch | The Internet of Things on AWS – Official Blog

或者,根据您测量温度的系统,您可以直接将指标发送到 CloudWatch 而不是 IoT。

以下是 Amazon CloudWatch 发送到 Amazon SNS 的示例消息,该消息随后将发送给 SNS 主题的所有订阅者:

From: AWS Notifications <no-reply@sns.amazonaws.com>
Date: Mon, 13 May 2019 at 08:03
Subject: ALARM: "Fluid Level alert" in Asia Pacific (Sydney)

You are receiving this email because your Amazon CloudWatch Alarm "Fluid Level alert" in the Asia Pacific (Sydney) region has entered the ALARM state, because "Threshold Crossed: 1 datapoint [10.5 (12/05/19 21:58:00)] was less than or equal to the threshold (15.0)." at "Sunday 12 May, 2019 22:03:17 UTC".

View this alarm in the AWS Management Console:
https://console.aws.amazon.com/cloudwatch/home?region=ap-southeast-2#s=Alarms&alarm=Fluid%20Level%20alert

Alarm Details:
- Name:                       Fluid Level alert
- Description:                Fluid level has dropped below 15
- State Change:               INSUFFICIENT_DATA -> ALARM
- Reason for State Change:    Threshold Crossed: 1 datapoint [10.5 (12/05/19 21:58:00)] was less than or equal to the threshold (15.0).
- Timestamp:                  Sunday 12 May, 2019 22:03:17 UTC

Threshold:
- The alarm is in the ALARM state when the metric is LessThanOrEqualToThreshold 15.0 for 300 seconds. 

Monitored Metric:
- MetricNamespace:                     Vat12
- MetricName:                          FluidLevel
- Dimensions:                          
- Period:                              300 seconds
- Statistic:                           Average
- Unit:                                not specified


State Change Actions:
- OK: 
- ALARM: [arn:aws:sns:ap-southeast-2::alertme]
- INSUFFICIENT_DATA: 

【讨论】:

  • 您能否自定义 CloudWatch 警报内容,让非技术人员更容易理解?或者您是否建议 SNS 生成一封电子邮件,这就是将收到的警报?
  • 无法自定义从 CloudWatch 发送到 SNS(因此也发送到 SNS 主题的订阅者)的消息。我在上面添加了一条示例消息。如果您希望自定义消息,则需要 SNS 来触发 AWS Lambda 函数,该函数可以通过 Amazon Simple Email Service (SES) 发送自定义电子邮件。
【解决方案3】:

通过引入 AWS IoT Events 服务解决了这个问题。

https://aws.amazon.com/iot-events/

我创建了一个检测器模型,该模型调用一个通过 SNS 主题发送电子邮件的 Lambda 函数。

在推出这项服务之前,需要定制开发以通过电子邮件实现按时间顺序的警报。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-26
    • 2021-02-15
    • 2021-12-01
    • 2020-07-08
    • 2016-03-16
    • 2021-01-22
    • 2023-03-18
    • 1970-01-01
    相关资源
    最近更新 更多