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

AWS Lambda Node.js函数重复调用出现Promise拒绝及运行时退出错误排查

问题排查:AWS Lambda快速连续调用时的异常问题

现象描述

  • 首次调用Lambda函数成功,返回结果正常
  • 再次快速调用时,返回Error: Runtime exited with error: exit status 128和ERROR Unhandled Promise Rejection Runtime.UnhandledPromiseRejection
  • 失败调用后再次调用,函数又能正常运行并返回正确结果
  • 已设置context.callbackWaitsForEmptyEventLoop = false,但问题依旧

排查方向及修复建议

1. 数据库连接缓存的潜在问题

代码中仅缓存了MongoDB的db实例,未缓存client实例。当Lambda复用执行环境时,若client连接失效或被销毁,缓存的db实例会处于不可用状态,导致后续调用失败。

修复方案:同时缓存client和db,并添加连接有效性检查:

const MongoClient = require("mongodb").MongoClient;
const ObjectId = require("mongodb").ObjectId;

const MONGODB_URI = process.env.MONGODB_URI;

let cachedClient = null;
let cachedDb = null;

async function connectToDatabase() {
  if (cachedDb && cachedClient && cachedClient.isConnected()) {
    return cachedDb;
  }

  const client = await MongoClient.connect(MONGODB_URI, {
    maxPoolSize: 10,
    connectTimeoutMS: 30000,
    socketTimeoutMS: 30000
  });

  const db = await client.db(process.env.MONGODB_NAME);

  cachedClient = client;
  cachedDb = db;
  return db;
}

2. 未处理的Promise拒绝

代码在catch块中仅打印错误,未返回错误响应。当Lambda函数抛出未处理的Promise拒绝时,会触发运行时异常,进而导致exit status 128进程终止错误。

修复方案:在catch块中返回标准错误响应,确保所有执行路径都有返回值:

try {
  // ... 原有业务逻辑
} catch (error) {
  console.error(error);
  return {
    statusCode: 500,
    headers: {
      "Access-Control-Allow-Headers": "*",
      "Access-Control-Allow-Origin": "http://localhost:3000/",
      "Access-Control-Allow-Methods": "*"
    },
    body: JSON.stringify({ error: error.message })
  };
}

3. 输入参数校验缺失

快速连续调用时,可能存在参数未定义或格式错误的情况(比如event.queryStringParameters为undefined、event.body为空),导致JSON.parse(event.body)抛出错误,触发未处理的Promise拒绝。

修复方案:添加参数校验逻辑,避免非法输入导致崩溃:

exports.handler = async (event, context) => {
  console.log(event.queryStringParameters);
  console.log(event.body);
  
  // 校验查询参数是否存在
  if (!event.queryStringParameters) {
    return {
      statusCode: 400,
      headers: {
        "Access-Control-Allow-Headers": "*",
        "Access-Control-Allow-Origin": "http://localhost:3000/",
        "Access-Control-Allow-Methods": "*"
      },
      body: JSON.stringify({ error: "缺少查询参数" })
    };
  }

  const { docType, docId, fundId } = event.queryStringParameters;
  // 校验必要参数
  if (!docType || !docId || !fundId) {
    return {
      statusCode: 400,
      headers: {
        "Access-Control-Allow-Headers": "*",
        "Access-Control-Allow-Origin": "http://localhost:3000/",
        "Access-Control-Allow-Methods": "*"
      },
      body: JSON.stringify({ error: "缺少必要参数:docType、docId、fundId" })
    };
  }

  // 校验请求体格式
  let bodyData;
  try {
    bodyData = JSON.parse(event.body || "{}");
  } catch (parseError) {
    return {
      statusCode: 400,
      headers: {
        "Access-Control-Allow-Headers": "*",
        "Access-Control-Allow-Origin": "http://localhost:3000/",
        "Access-Control-Allow-Methods": "*"
      },
      body: JSON.stringify({ error: "请求体格式错误" })
    };
  }

  // ... 原有业务逻辑
};

4. 并发更新冲突处理

快速连续调用时,可能出现同一文档被并发更新的情况,导致MongoDB抛出异常。虽然使用了findOneAndUpdate,但未处理冲突会引发错误。

修复方案:添加重试逻辑处理并发冲突:

async function updateDocument(db, docType, docId, fundId, bodyData) {
  let retryCount = 0;
  const maxRetries = 3;
  
  while (retryCount < maxRetries) {
    try {
      return await db.collection(docType).findOneAndUpdate(
        { _id: ObjectId(docId), "profile_subscription_documents.fund_id": fundId },
        { $push: { "profile_subscription_documents.$[psd].profile_fund_subscription_documents": { ...bodyData } } },
        { arrayFilters: [{ "psd.fund_id": fundId }], returnDocument: "after" }
      );
    } catch (updateError) {
      retryCount++;
      if (retryCount >= maxRetries) throw updateError;
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }
}

// 在handler中调用
const data = await updateDocument(db, docType, docId, fundId, bodyData);

总结

优先排查未处理的Promise拒绝和数据库连接缓存有效性这两个核心问题,它们是导致exit status 128和调用失败的常见原因。同时完善参数校验和错误处理逻辑,可大幅提升函数稳定性。

内容的提问来源于stack exchange,提问作者Rich

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 21:37:37