为什么 Amazon SNS 不调用我的 AWS Lambda 函数,我该如何解决问题?
上次更新时间:2021 年 6 月 3 日
我正在使用 AWS Lambda 函数来处理 Amazon Simple Notification Service (Amazon SNS) 通知,但我的 Amazon SNS 主题没有调用该函数。如何对未调用 Lambda 函数的 Amazon SNS 通知进行故障排除?
简短描述
Amazon SNS 消息事件无法调用订阅了 SNS 主题的 Lambda 函数有五个原因:
- 向 SNS 主题发布的 AWS Identity and Management (IAM) 身份没有发布到 SNS 主题所需的权限。
- Lambda 函数没有允许 Amazon SNS 调用该函数所需的权限。
- Lambda 函数的 SNS 主题订阅具有与从 SNS 主题发送的消息属性不匹配的筛选条件策略。
- Lambda 函数受到限制,因为它接近超过其托管在 AWS 区域的账户级别并发配额。
- Amazon SNS 主题在商业 AWS 区域中托管,Lambda 函数托管在选择加入区域中。
注意:有关 Amazon SNS 支持的 AWS 区域的当前列表,请参阅 Amazon Simple Notification Service 终端节点和配额。
解决方法
重要提示:如果您尚未这样做,请为 Amazon SNS 主题配置 Amazon CloudWatch 交付状态日志记录。有关更多信息,请参阅使用 CloudWatch 监控 Amazon SNS 主题。
确认向 SNS 主题发布的 IAM 身份具有发布到 SNS 主题所需的权限
请查看适用于 Amazon SNS 的 Amazon CloudWatch 指标中的 NumberOfMessagesPublished 的指标。如果您用来调用函数的 IAM 实体发出的发布请求没有记录在 NumberOfMessagesPublished 指标中,请执行以下操作:
1. 确认发出 Publish API 请求的 IAM 实体具有发布到 SNS 主题所需的权限。有关更多信息和具体策略声明示例,请参阅 Amazon SNS 访问控制示例案例。
2. 确认 SNS 主题的权限策略允许进行 Publish API 调用的 IAM 实体使用 “SNS:Publish”操作。有关更多信息和示例权限策略,请参阅 Amazon SNS 的权限主题。
确认您的 Lambda 函数具有允许 Amazon SNS 调用该函数所需的权限
要查看函数的权限策略,请按照对 AWS Lambda 使用基于资源的策略中的说明进行操作。如果函数的策略不包括 SNS 主题的“lambda:invokeFunction”操作,请更新策略以包含所需的权限。
请确认您的 Lambda 函数的筛选条件策略与从 SNS 主题发送的消息属性匹配
查看适用于 Amazon SNS 的 CloudWatch 指标中的 NumberOfNotificationsFilteredOut 指标。如果您用来调用函数并由 IAM 实体发出的发布请求出现在 NumberOfNotificationsFilteredOut 指标中,请执行以下操作:
1. 通过执行以下操作查看 Lambda 函数的 SNS 主题订阅筛选条件策略:
打开 Amazon SNS 控制台。
在左侧导航窗格上,选择 Subscriptions(订阅)。
在 Edit 页面上,展开 Subscription filter policy(订阅筛选条件策略)部分。
2. 查看订阅筛选条件策略以确认 Publish 请求消息属性与筛选条件策略所要求的属性匹配。如果属性不匹配,请更新 Publish 请求消息属性,使其与筛选条件策略所需的属性匹配。
注意:有关更多信息,请参阅 Amazon SNS 订阅筛选条件策略。
确认您的 Lambda 函数没有受到限制
(对于在商业区域中托管的 SNS 主题)确认您的 Lambda 函数与 SNS 主题位于同一个区域
注意:托管在商业 AWS 区域中的 Amazon SNS 主题无法调用不在商业区域内的 Lambda 函数。有关 Amazon SNS 支持的 AWS 区域的当前列表,请参阅 Amazon Simple Notification Service 终端节点和配额。
查看您的 Lambda 函数的 Amazon Resource Name (ARN) 和 Amazon SNS 主题。如果 Amazon SNS 主题托管在商业 AWS 区域中,并且该函数托管在选择加入区域中,请执行以下操作:
1. 在与 Amazon SNS 主题所在相同的区域中创建新的 Lambda 函数。
2. 配置函数的设置,以便它对托管在选择加入区域中的函数进行 Invoke API 调用。
重要提示:确保更新 SDK 区域设置。
用于更改区域设置的 Python (Boto 3) 命令示例
#us-east-1 client
lambda_us_east_1_client = boto3.client('lambda', region_name='us-east-1')
#us_west_1 client
lambda_us_west_1_client = boto3.client('lambda', region_name='us-west-1')
用于更改区域设置的 JavaScript/Node.js 命令示例
//us-east-1 client
var lambda_us_east_1_client = new AWS.Lambda({apiVersion: '2015-03-31',region: 'us-east-1'});
//us_west_1 client
var lambda_us_east_1_client = new AWS.Lambda({apiVersion: '2015-03-31', region: 'us-west-1'});