AWS Lambda调用SNS重复发送邮件问题排查求助
排查AWS Lambda调用SNS发送重复邮件问题
可能原因及排查步骤
1. Lambda函数自动重试导致重复执行
Lambda默认会对执行超时、运行时错误、服务错误等情况自动重试(异步执行最多重试2次,同步执行视调用方逻辑而定)。即便未配置额外触发器,函数报错也可能触发多次执行。
- 排查方法:
- 进入Lambda控制台,查看函数监控页面的
Invocation count指标,确认单次触发是否对应多次调用。 - 打开CloudWatch日志,搜索函数请求ID,检查是否存在同一请求ID的多条日志记录(重复日志即代表重试)。
- 进入Lambda控制台,查看函数监控页面的
- 解决方法:
- 修复函数内的报错问题,从根源避免触发重试。
- 若为异步执行场景,在Lambda异步调用配置中关闭重试,或配置死信队列接收失败请求。
2. SNS主题存在重复邮箱订阅
如果目标邮箱被多次订阅到同一SNS主题,每次调用publish都会给所有订阅者发送邮件,自然会收到多封重复邮件。
- 排查方法:
- 进入SNS控制台,找到目标主题,查看订阅列表,确认是否存在同一邮箱的多条订阅记录(无论状态是否为已确认)。
- 解决方法:
- 删除重复的订阅记录,确保每个邮箱仅订阅一次目标主题。
3. 代码逻辑中多次调用SNS publish方法
检查代码是否存在循环调用boto3.client('sns').publish()的情况,或在分支逻辑中重复触发发送操作。
- 排查要点:
- 搜索代码中的
publish关键字,确认调用次数是否符合预期。 - 若处理批量事件(如SQS触发器的批量消息),检查是否未做去重就循环发送了多次。
- 搜索代码中的
- 错误示例(循环内重复发送):
sns_client = boto3.client('sns') # 错误:循环遍历消息时每次都发送邮件 for item in event['Records']: sns_client.publish( TopicArn='arn:aws:sns:us-east-1:123456789012:MyTopic', Message='Test email', Subject='Test' ) - 解决方法:
- 确保
publish仅被调用一次,或在批量处理时合并消息后统一发送。
- 确保
4. 手动限流逻辑失效
你提到每次运行后需手动限流,说明代码中的限流逻辑可能未生效,导致函数重复触发或重复发送。
- 排查方法:
- 检查限流逻辑实现:比如是否用DynamoDB做幂等键、Redis做分布式锁,确认锁的有效期、键的唯一性是否正确。
- 确认幂等键是否基于请求唯一标识(如Lambda的
requestId或业务唯一ID),避免不同请求被误限流,同时保证同一请求不会重复执行。
- 幂等实现示例(基于DynamoDB):
import boto3 from botocore.exceptions import ClientError dynamodb = boto3.client('dynamodb') sns_client = boto3.client('sns') def lambda_handler(event, context): request_id = context.request_id # 校验请求是否已处理 try: dynamodb.put_item( TableName='IdempotencyTable', Item={'RequestId': {'S': request_id}}, ConditionExpression='attribute_not_exists(RequestId)' ) except ClientError as e: if e.response['Error']['Code'] == 'ConditionalCheckFailedException': # 已处理过该请求,直接返回 return {'statusCode': 200, 'body': 'Already processed'} raise # 执行邮件发送逻辑 sns_client.publish( TopicArn='arn:aws:sns:us-east-1:123456789012:MyTopic', Message='Test email', Subject='Test' ) return {'statusCode': 200, 'body': 'Success'}
额外建议
- 若使用SNS FIFO主题,给消息添加
MessageDeduplicationId和MessageGroupId,可避免重复消息投递。 - 在Lambda函数中添加日志,记录每次调用
publish的时间和请求ID,便于追踪重复发送的来源。
内容的提问来源于stack exchange,提问作者Dinho
相关产品推荐
相关产品推荐

