You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:02:05