为什么 Amazon SNS 不在 CloudWatch 警报触发 Lambda 函数时调用该函数?

上次更新日期:2021 年 6 月 24 日

我希望 Amazon Simple Notification Service (Amazon SNS) 在 Amazon CloudWatch 警报触发 AWS Lambda 函数时调用该函数。

简短描述

以下情况会阻止您调用 Lambda 函数:

  • Lambda 函数的资源策略尚未授予从 SNS 主题调用该函数的权限。对于此种情况,请完成查看 Lambda 函数基于资源的策略文档部分中的步骤。
  • Lambda 函数调用延迟。对于此种情况,请完成查看您的 Amazon SNS 传输日志部分中的步骤。

注意:以下解决方法假定您可以在 SNS 主题上调用 Publish API,但在 Amazon SNS 和 Lambda 集成之间出现错误。如果在您的 SNS 主题上看不到任何活动,请参阅为什么我没有收到 CloudWatch 警报触发的 SNS 通知? 该活动可以包括以下 CloudWatch 指标:NumberOfMessagesPublishedNumberOfNotificationsDeliveredNumberOfNotificationsFailed

解决方法

注意:如果您在运行 AWS Command Line Interface (AWS CLI) 命令时遇到错误,请确保您使用的是最新版 AWS CLI

查看 Lambda 函数基于资源的策略文档

当 Amazon SNS 异步调用 Lambda 函数时,Lambda 将 202 HTTP 状态代码返回给 Amazon SNS。状态代码显示 Lambda 已接受该消息供以后处理。有关更多信息,请参阅异步调用。如果响应失败,可以查看 Amazon SNS 传输日志以了解更多信息。

根据账户中的情况选择解决方法。

如果您的 SNS 主题和 Lambda 函数位于同一账户中:

1.    打开 Lambda 控制台

2.    在导航窗格上选择 Functions (函数),然后选择您的函数。

3.    选择 Configuration (配置) 选项卡,然后选择 Permissions (权限)

4.    在基于资源的策略部分中,从 Statement ID (声明 ID) 列中选择策略声明以查看您的策略文档。您会看到以下策略文档:

statement id
your-statement-id

principal:
sns.amazonaws.com

effect
allow

action
Lambda:InvokeFunction

conditions
{ "arnlike": { "aws:sourcearn": "arn:aws:sns:your-aws-region:your-aws-account-id:your-sns-topic-name" } 

注意:要以 JSON 格式查看您的策略文档,请在基于资源的策略部分中选择查看策略文档

如果您缺少授予 Amazon SNS 调用该函数的权限的 Lambda 资源策略,请将以下函数添加到您的策略文档中。您可以使用 Lambda 控制台、 AWS CLIAWS CloudShell

使用命令行:

aws lambda add-permission \
--function-name your-lambda-function-name \
--statement-id triggerfromsns-statement-id \
--action lambda:invokefunction \
--principal sns.amazonaws.com \
--source-arn arn:aws:sns:your-aws-region:your-aws-account-id:your-sns-topic-name

注意:your-lambda-function-nameyour-aws-regionyour-aws-account-idyour-sns-topic-name 替换为您的值。AWS CLI 命令使用默认 AWS 区域。如果 Lambda 函数位于其他区域,可以使用 --region 标记覆盖默认区域。

打开 Lambda 控制台:

1.    打开 Lambda 控制台

2.    在导航窗格上选择 Functions (函数),然后选择您的函数。

3.    选择 Configuration (配置) 选项卡,再选择 Permissions (权限)

4.    在基于资源的策略部分中,选择 Add permissions (添加权限)

5.    对于 Principal (委托人),请选择 sns.amazonaws.com

6.    对于 Actions (操作),请选择 Lambda:InvokeFunction

7.    对于 Statement ID (声明 ID),请输入唯一 ID。

8.    选择 Save (保存)

如果您的 SNS 主题和 Lambda 函数位于不同账户中:

1.    设置跨账户权限

2.    在您的 CloudWatch 日志中,使用传输状态日志记录验证 Amazon SNS 是否已成功向 Lambda 或 NumberOfNotificationsDelivered CloudWatch 指标发送消息。

Amazon SNS 和 Lambda 之间的成功响应示例:

{
    "notification": {
        "messagemd5sum": "your-md5-sum",
        "messageid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "topicarn": "arn:aws:sns:your-aws-region:your-aws-account-id:your-sns-topic",
        "timestamp": "2021-04-04 14:08:48.083"
    },
    "delivery": {
        "deliveryid": "your-sns-delivery-id",
        "destination": "arn:aws:lambda:your-aws-region:your-aws-account-id:function:your-function-name",
        "providerresponse": "{\ "lambdarequestid\":\ "your-lambda-request-id\"}",
        "dwelltimems": 92,
        "attempts": 1,
        "statuscode": 202
    },
        "status": "success"
}

查看您的 Amazon SNS 传输日志

查看您的 SNS 主题针对 Lambda 函数的传输日志。 如果响应成功,您会看到 202 状态代码。

要查看 SNS 主题的 CloudWatch 日志,请执行以下操作:

1.    打开 CloudWatch 控制台

2.    在导航窗格上,展开 Logs (日志),然后选择 Log groups (日志组)

3.    在筛选器搜索框中,输入 SNS 主题的名称。将显示 SNS 主题的两个日志组:一个为成功日志组,一个为失败日志组。

4.    选择成功日志组。

5.    在 Log streams (日志流) 部分,选择 Search all (搜索所有)

注意:您还可以在 Last event time (上次事件时间) 列中查看请求的时间戳。然后,搜索 Lambda 函数的 Amazon Resource Name (ARN) 和名称。

6.    从 Log stream (日志流) 列中,选择日志流以将其打开。

如果未显示任何结果,请执行以下操作:

1.    选择 Log groups (日志组),然后选择失败日志组。

2.    在 Log streams (日志流) 部分,选择 Search all (搜索所有)

3.    从 Log stream (日志流) 列中,选择日志流以将其打开。

要排查失败的日志组,请执行以下操作:

1.    检查 Lambda 函数的 X-Ray 跟踪停留时间是否较长。如果停留时间较长,请使用 CloudWatch 控制台验证您在该区域的 Lambda 函数的错误和限制数是否最少。请务必选择所有函数,然后选择 Errors (错误)Throttles (限制) 指标。

注意:异步调用的函数之间存在数百个错误和限制会备份内部 Lambda 队列,从而导致函数调用延迟。将错误和限制率保持最低水平是最佳做法,这样就可避免函数调用的不必要延迟。有关更多信息,请参阅异步调用

2.    设置目标 Amazon Simple Queue Service (Amazon SQS) 队列或 Lambda 函数以进行单独处理。这可以防止消息丢失,而且这样做是因为对于 Lambda 函数来说,异步事件最长可持续 6 个小时。


这篇文章对您有帮助吗?


您是否需要账单或技术支持?