AWS Lambda - Nodejs:分配失败 - JavaScript 堆内存不足

Posted

技术标签:

【中文标题】AWS Lambda - Nodejs:分配失败 - JavaScript 堆内存不足【英文标题】:AWS Lambda - Nodejs: Allocation failed - JavaScript heap out of memory 【发布时间】:2018-09-29 23:43:18 【问题描述】:

我正在使用 Lambda (nodeJS) 来查询 noSQL 数据 (dynamo db)。

假设我在 DynamoDB 中有“学生”表,并且我有一个 API,它返回特定班级的学生列表 (class_id)。 (我用的是“查询”)

据我所知,发电机对结果进行分页,所以我的 API 如下所示:

class_id : 'xxxx' => 返回第一个学生名单 class_id : 'xxxx', last_evaluated_key: .... => 返回下一个学生列表(如果 LastEvaluatedKey 存在)

我的 lambda 代码:

exports.handler = function(e, ctx, callback) 
    var rp = require('request-promise');

    var students = [];

    var hasMore = true;
    var params = 
        class_id: e.class_id
    

    while (hasMore) 
        var options = 
            method: 'POST',
            uri: 'https://xxxxxx.eu-west-1.amazonaws.com/dynamodliblightdm-gobject-1-0:amd64liblightdm-gobject-1-0:amd64b/getStudents',
            body: params,
            json: true // Automatically stringifies the body to JSON
        ;

        rp(options)
            .then(function(repos) 
                console.log('count: ' + repos.Count);
                students.push(repos.Items);

                if (repos.hasOwnProperty("LastEvaluatedKey")) 
                    params['last_evaluated_key'] = repos.LastEvaluatedKey;
                 else 
                    hasMore = false;
                

            )
            .catch(function(err) 
                console.log('Error', err);
            );
    


    callback(null, 'done.');

我收到错误:

42676 毫秒:标记扫描 804.1 (954.3) -> 802.7 (954.3) MB,1803.0 / 0.0 ms (+ 246.3 ms,自打标开始后 32 步,最大步长 35.7 ms) [分配失败] [请求旧空间中的 GC]。 44415 毫秒:标记扫描 802.7 (954.3) -> 802.7 (954.3) MB,1738.6 / 0.0 毫秒 [分配失败] [请求旧空间中的 GC]。 46318 毫秒:标记扫描 802.7 (954.3) -> 809.5 (859.3) MB,1902.9 / 0.0 毫秒 [最后的 gc]。 48184 ms:标记扫描 809.5 (859.3) -> 816.4 (858.3) MB,1865.7 / 0.0 ms [最后的 gc]。 ==== JS 堆栈跟踪 ========================================== 安全上下文:0x322e8723fa99 2:新构造函数(又名 Multipart)[/var/task/lambda-func/node_modules/request/lib/multipart.js:~8] [pc=0x1b47df3f5f98] (this=0x1175e583149 ,request=0x1175e582fa9 ) 4:新构造函数(又名请求)[/var/task/lambda-func/node_modules/request/request.js:125] [pc=0x1b47df4df3e6](这=0x1175e... 致命错误:CALL_AND_RETRY_LAST 分配失败 - javascript 堆内存不足 1: node::Abort() [/var/lang/bin/node] 2:0x55d79ff0b302 [/var/lang/bin/node] 3: v8::Utils::ReportApiFailure(char const*, char const*) [/var/lang/bin/node] 4: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/var/lang/bin/node] 5: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/var/lang/bin/node] 6: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/var/lang/bin/node] 7:0x1b47df2062bf

欢迎提出任何建议。

【问题讨论】:

看起来像无限循环。 while 循环不会等到您的承诺得到解决。它只是一遍又一遍地调用同样的东西 嗨@yBrodsky,我可以看到问题来自while循环,我的问题是如何在while循环中使用'request-promise',或者更大的问题是如何从dynamodb获取所有项目正确。 【参考方案1】:

建议获得所有学生。

const fetch  = (lastEvaluatedKey)  => 
  return rp().then((res) => 
    students = students.concat(res.moreStudents);
    if(res.shouldKeepFetching) 
      return fetch(res.lastKey);
    

    return Promise.resolve();
  )


fetch().then(() => 
  //you fetched them all
)

如果有大量学生,这可能会给您带来另一个内存不足的问题。 你可以做的另一件事,但我不知道 lambda 是否允许它,是使用带有 async/await 的 for 循环

【讨论】:

以上是关于AWS Lambda - Nodejs:分配失败 - JavaScript 堆内存不足的主要内容,如果未能解决你的问题,请参考以下文章

使用 AWS Lambda 和 API Gateway NodeJs 的格式错误的 Lambda 代理响应

AWS Lambda 无法调用没有 VPC 的另一个 AWS Lambda - NodeJs

使用 AWS Lambda (NodeJS) 创建 AWS AppSync

在 NodeJS + Typescript AWS Lambda 上进行单元测试

AWS Lambda NodeJS导入返回空模块,但仅在AWS中

使用 AWS api 网关 + lambda + Nodejs 的私有和公共 ip