AWS Lambda触发TooManyRequestsException异常求助:仅调用14次却超限
问题分析与解决方案
为什么14次调用会触发并发限制?
AWS Lambda的账户级默认并发是1000,但单个函数的预留并发默认是0,此时函数会共享账户的并发池。如果你的账户内其他函数正在占用大量并发,或者Lambda B被手动设置了低于14的预留并发值,就会触发ConcurrentInvocationLimitExceeded错误。另外,同步调用(RequestResponse)会实时占用并发资源,14次同时发起直接耗尽了该函数可用的并发额度。
架构层面解决方案
- 调整Lambda B的并发配置:进入Lambda控制台,找到
scraper函数,查看「配置」-「并发」设置。如果设置了预留并发且值小于14,调高至至少14;或者将预留并发设为0,让函数使用账户级并发池(前提是账户有足够剩余并发)。 - 改用SQS做任务缓冲:将Lambda A的同步调用改为异步调用(
InvocationType: 'Event'),把抓取任务发送到SQS队列,再配置Lambda B作为SQS的触发器,通过SQS的「批量大小」和Lambda B的并发设置控制同时执行的任务数,避免瞬间并发过载。 - 使用Step Functions编排:用Step Functions的
Parallel状态来执行抓取任务,通过MaxConcurrency参数精确控制并行执行的Lambda B数量(比如设为10),既保证效率又不会触发并发限制。 - 合并抓取逻辑(可选):如果单个抓取任务耗时短(比如几秒内),可以把Lambda B的抓取代码整合到Lambda A中,避免跨Lambda调用的并发限制问题,但要注意Lambda A的最大执行时间限制(15分钟)。
代码层面解决方案
方案1:分批执行调用(控制并发数)
把一次性Promise.all改成分批执行,比如每次执行5个任务,完成一批再执行下一批:
const handler = async (event) => { const sources = await connect(databaseUrl); if (sources === "err") { console.error("数据库连接失败"); return JSON.stringify({ error: "数据库连接失败" }); } // 分批执行,每批5个 const batchSize = 5; const results = []; for (let i = 0; i < sources.length; i += batchSize) { const batch = sources.slice(i, i + batchSize); const batchPromises = batch.map(source => invoke(client, source)); const batchResults = await Promise.all(batchPromises); results.push(...batchResults); } const decoder = new TextDecoder('utf-8'); results.forEach(result => { console.log(decoder.decode(result.Payload)); }); return JSON.stringify(results); };
方案2:添加重试机制(指数退避)
在invoke函数中添加针对TooManyRequestsException的重试逻辑:
const invoke = async (client, source) => { const params = { FunctionName: 'scraper', InvocationType: 'RequestResponse', Payload: JSON.stringify(source) }; let retries = 3; let delay = 1000; while (retries > 0) { try { return await client.send(new InvokeCommand(params)); } catch (err) { if (err.name === 'TooManyRequestsException' && retries > 0) { retries--; await new Promise(resolve => setTimeout(resolve, delay)); delay *= 2; // 指数退避 } else { throw err; } } } throw new Error("重试次数耗尽"); };
方案3:优化Lambda B执行效率
- 优化抓取逻辑:使用更快的HTTP库(如
undici替代axios/node-fetch),减少不必要的DOM解析操作。 - 复用连接:如果抓取需要建立持久连接,在Lambda B的全局上下文复用连接,避免每次调用重新建立连接的开销。
内容的提问来源于stack exchange,提问作者hilaw00
相关产品推荐
相关产品推荐

