如何限制AWS Lambda函数每分钟向外部API发起的请求次数?
解决方案
方案1:基于DynamoDB的固定窗口限流
利用DynamoDB原子操作维护全局请求计数,结合SQS延迟队列处理超限请求:
- 创建DynamoDB表,主键设为
minute_key(格式如YYYYMMDDHHMM,对应当前分钟),额外字段request_count记录该分钟已发送请求数。 - Lambda触发时,先通过
UpdateItem原子操作更新计数:response = dynamodb.update_item( TableName='RateLimitTable', Key={'minute_key': {'S': current_minute}}, UpdateExpression='ADD request_count :incr', ExpressionAttributeValues={':incr': {'N': '1'}}, ConditionExpression='request_count < :limit', ExpressionAttributeValues={':limit': {'N': '100'}}, # 替换为API的每分钟限制数 ReturnValues='UPDATED_NEW' ) - 若
UpdateItem成功(未触发条件失败),直接调用目标API;若失败(计数超限),将请求参数发送到SQS延迟队列,延迟时间设为当前分钟剩余秒数(比如当前是第35秒,延迟25秒),等下一分钟再处理。 - 定时清理DynamoDB中过期的分钟记录(比如保留最近1小时数据),避免表膨胀。
方案2:用Step Functions实现精准速率控制
通过Step Functions编排请求流程,严格控制每分钟请求量:
- 创建Step Functions状态机,用CloudWatch Events设置每分钟触发一次,每次触发时从SQS队列取出最多N条消息(N为API的每分钟限制数),批量调用Lambda处理并发送请求。
- 将原Lambda逻辑拆分:第一部分接收原始信号并将请求参数发送到SQS队列;第二部分由Step Functions触发,负责从队列取消息并调用目标API。
- 这种方式完全规避Lambda并发的不确定性,直接通过调度器控制每分钟请求总量,不会出现超限情况。
方案3:ElastiCache Redis分布式令牌桶(进阶方案)
用Redis实现分布式令牌桶,解决多Lambda实例的限流共享问题:
- 在ElastiCache中创建Redis集群,维护全局令牌桶:每分钟向桶中放入N个令牌(N为API限制数)。
- Lambda调用时,先从Redis中获取1个令牌,获取成功则执行请求;否则将请求参数放入SQS队列等待下一轮令牌生成。
- 注意配置Redis的过期策略,避免令牌堆积。
关键注意事项
- 所有限流逻辑不依赖目标API的查询接口,防止消耗请求额度。
- 为SQS配置死信队列,处理多次重试仍失败的请求,避免消息丢失。
- DynamoDB和Redis的操作要设置合理重试策略,应对并发冲突。
内容的提问来源于stack exchange,提问作者vwy089
相关产品推荐
相关产品推荐

