ฟังก์ชัน AWS Lambda สามารถอัปเดตบันทึกทั้งหมดในตาราง DynamoDB ได้อย่างไร

ฉันกำลังทำงานกับฟังก์ชัน AWS Lambda (โหนด 4.3) ที่ต้องรันผ่านรายการทั้งหมดในตาราง DynamoDB และอัปเดตคุณลักษณะบางอย่าง

ปัญหาที่ฉันมีคือจะทำให้ Lambda รอจนกว่าการดำเนินการ DynamoDB ทั้งหมดจะเสร็จสิ้นได้อย่างไร

var async = require('async');
var aws = require('aws-sdk');
var doc = new aws.DynamoDB.DocumentClient();

exports.handler = (event, context, callback) => {
    doc.scan({
        TableName: 'Occupations_dev'
    }, function (err, data) {
        console.log(data.Items.length);

        var funcs = [];

        data.Items.forEach(function (item) {
            funcs.push(function (cb) {
                item.Popularity = 0;

                doc.put({
                    TableName: 'Occupations_dev',
                    Item: item
                }, function (err, data) {
                    if (err) {
                        console.log("ERROR: " + item.Name);
                        cb(err);
                    } else {
                        console.log('Finished put for ' + item.Id)
                        cb(null, item);
                    }
                });
            });
        });

        async.parallel(funcs, function (err, results) {
            console.log('Finished');

            if (err) {
                context.fail(err);
            } else {
                callback(null, 'Finished');
            }
        });
    });
};

ฉันลองใช้ async.parallel เพื่อรอให้คำขอ db.put ทั้งหมดเสร็จสิ้น แต่จบลงด้วยข้อผิดพลาด Process exited before completing request ทุกครั้งที่ฟังก์ชัน Lambda ทำงาน

โดยจะอัปเดตรายการ DynamoDB บางส่วน แต่ไม่ใช่ทั้งหมดอย่างแน่นอน

ฉันเพิ่มการเรียก console.log บางส่วนเมื่อมีข้อผิดพลาด แต่ผลลัพธ์เดียวที่ฉันเห็นในบันทึกคือ:

START RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870 Version: $LATEST
2017-03-30T02:08:11.691Z    b72fd7c6-14ed-11e7-a95a-c1185af4e870    1362
END RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870
REPORT RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870  Duration: 37165.80 ms   Billed Duration: 37200 ms   Memory Size: 128 MB Max Memory Used: 128 MB 
RequestId: b72fd7c6-14ed-11e7-a95a-c1185af4e870 Process exited before completing request

วิธีที่เหมาะสมในการทำให้ฟังก์ชัน Lambda รอจนกว่าทุกอย่างจะเสร็จสิ้นคืออะไร (ข้อมูลมีไม่มากนัก ดังนั้นฉันจึงไม่กังวลกับการทำงานนานกว่า 5 นาทีและหมดเวลา)


person Mark Biek    schedule 30.03.2017    source แหล่งที่มา
comment
ฉันคิดว่า Process exited before completing request หมายความว่ามีข้อผิดพลาดอื่น ๆ ในโค้ด js ของคุณ - ใช้งานได้ในเครื่องและมีข้อผิดพลาดเฉพาะบน AWS Lambda หรือไม่   -  person Bobby Matson    schedule 30.03.2017
comment
ฉันค่อนข้างใหม่กับ Lambda ดังนั้นฉันจึงไม่รู้ว่าจะเรียกใช้มันในเครื่องได้อย่างไร มีวิธีรับรายละเอียดข้อผิดพลาดเพิ่มเติมจาก Lambda หรือไม่ ฉันไม่เห็นสิ่งใดในบันทึกของ CloudWatch   -  person Mark Biek    schedule 30.03.2017
comment
น่าแปลกที่พวกเขาน่าจะอยู่ใน Cloudwatch ฉันเชื่อว่า เมื่อคุณเรียกใช้ข้อมูลโค้ด คุณเห็นคำสั่ง console.log ใดๆ หรือไม่ สิ่งเหล่านั้นควรมาจากเอาต์พุตบันทึกใน Lambda   -  person Bobby Matson    schedule 30.03.2017
comment
ฉันเพิ่มคำสั่ง console.log บางคำสั่งเมื่อ doc.put มีข้อผิดพลาด แต่ฉันไม่เห็นบันทึกใด ๆ เลย ฉันเห็นเฉพาะผลลัพธ์ของ console.log(data.Items.length); และประมาณ 60 ของคำสั่ง Finished put for... ก่อนที่มันจะตาย   -  person Mark Biek    schedule 30.03.2017
comment
ป่า! DynamoDB มีข้อจำกัดใดๆ เกี่ยวกับการเชื่อมต่อพร้อมกันหรือไม่ หากคุณพยายามแทรกเรคคอร์ดแบบอะซิงโครนัสมากเกินไป อาจเกิดปัญหาได้ อาจลองใช้วิธีซิงโครนัส เช่น async.series หรือ Promise.all แล้วดูว่าผลลัพธ์ของคุณเหมือนกันหรือไม่   -  person Bobby Matson    schedule 30.03.2017
comment
นั่นเป็นความคิดที่น่าสนใจ ฉันจะลอง async.auto (หรืออาจจะ waterfall) แล้วดูว่าจะเกิดอะไรขึ้น ขอบคุณสำหรับความช่วยเหลือ!   -  person Mark Biek    schedule 30.03.2017
comment
ไม่มีปัญหา! ฉันแก้ไขความคิดเห็นล่าสุด ฉันคิดว่า async.series คือสิ่งที่คุณต้องการลองใช้ แจ้งให้เราทราบว่ามันเป็นอย่างไร!   -  person Bobby Matson    schedule 30.03.2017
comment
@BobbyMatson async.series ทำเคล็ดลับ! ดูเหมือนว่าคุณคิดถูกที่ฉันทำให้ DynamoDB มีการเชื่อมต่อมากเกินไป คุณควรโพสต์สิ่งนั้นเป็นคำตอบเพื่อที่ฉันจะได้ยอมรับและให้เครดิตที่เหมาะสมแก่คุณ ขอบคุณอีกครั้ง. ฉันใช้เวลาทั้งวันอย่างแท้จริงในการพยายามคิดหาคำตอบนี้   -  person Mark Biek    schedule 30.03.2017
comment
จะทำ! ดีใจที่ได้ผล   -  person Bobby Matson    schedule 30.03.2017


คำตอบ (2)


การเรียกใช้ฟังก์ชัน async.parallel เกิดขึ้นแบบอะซิงโครนัส ซึ่งมีแนวโน้มว่าจะทำให้ DynamoDB ท่วมท้นด้วยการอัปเดตพร้อมกันหลายครั้ง และทำให้เกิดข้อผิดพลาด "การเชื่อมต่อมากเกินไป" ในระดับ DB

ฉันขอแนะนำให้ใช้การดำเนินการแบบซิงโครนัส เช่น async.series เพื่อดำเนินการอัปเดตฐานข้อมูล DynamoDB ไม่น่าจะมีปัญหาในการประมวลผลการอัปเดตเหล่านี้ทีละรายการ

person Bobby Matson    schedule 30.03.2017

ข้อความ "กระบวนการออกก่อนดำเนินการตามคำขอ" หมายความว่าฟังก์ชัน Javascript ออกก่อนที่จะเรียก context.done (หรือ context.succeed ฯลฯ)

นี่คือข้อเสนอแนะบางส่วน:

ก่อนอื่น ให้ลองเพิ่มขีดจำกัดหน่วยความจำสำหรับฟังก์ชันนี้ บรรทัดนี้ Memory Size: 128 MB Max Memory Used: 128 MB อาจระบุว่าหน่วยความจำไม่เพียงพอ และกระบวนการเพิ่งถูกฆ่าโดยไม่โทรกลับครั้งล่าสุด

สิ่งที่คุณอาจเห็นหลังจากเพิ่มขีดจำกัดหน่วยความจำคือหนึ่งในสิ่งต่อไปนี้:

  • ฟังก์ชันของคุณจะหมดเวลา ในกรณีนี้ คุณอาจต้องเพิ่มความจุที่จัดเตรียมไว้ของตาราง (และ/หรือการหมดเวลาแลมบ์ดาของคุณ)

  • แม้ว่าฟังก์ชันจะสิ้นสุดโดยไม่มีการหมดเวลา คุณอาจเห็นว่ามีการประมวลผลบันทึกตารางบางส่วนเท่านั้น เนื่องจากการสแกนและการสืบค้นอาจส่งคืนแถวในตารางไม่ทั้งหมด หากจำนวนรายการที่สแกนทั้งหมดเกินขีดจำกัดขนาดชุดข้อมูลสูงสุด 1 MB เมื่อการสแกนเสร็จสิ้น คุณควรตรวจสอบว่า LastEvaluatedKey ส่งคืนพร้อมกับข้อมูลหรือไม่ หากเป็นเช่นนั้น คุณควรทำการสแกนอีกครั้งโดยระบุค่า LastEvaluatedKey เป็นพารามิเตอร์ ExclusiveStartKey

person xtx    schedule 30.03.2017