繁体   English   中英

在 AWS Lambda 中读取事件 stream 时出现问题。Nodejs 代码在本地按需工作但在 AWS Lambda 中不起作用

[英]Problem in reading event stream in AWS Lambda. Nodejs code working locally as desired but not in AWS Lambda

这是工作流程:

获取 https 链接 --> 写入文件系统 --> 从文件系统读取 --> 获取 sha256 hash。

它在我运行节点 10.15.3 的本地机器上一切正常但是当我在 AWS 上启动 lambda function 时,output 是 null。一些问题可能在于可读的 stream。这是代码。 您可以直接在本地计算机上运行它。 它将 output a sha256 hash 根据需要。 如果您希望在 AWS Lambda 上运行,请按标记注释/取消注释。

//Reference: https://stackoverflow.com/questions/11944932/how-to-download-a-file-with-node-js-without-using-third-party-libraries



var https = require('https');
var fs = require('fs');
var crypto = require('crypto')
const url = "https://upload.wikimedia.org/wikipedia/commons/a/a8/TEIDE.JPG"
const dest = "/tmp/doc";
let hexData;


async function writeit(){
  var file = fs.createWriteStream(dest);
  return new Promise((resolve, reject) => {
    var responseSent = false;
    https.get(url, response => {
      response.pipe(file);
      file.on('finish', () =>{
        file.close(() => {
          if(responseSent)  return;
          responseSent = true;
          resolve();
        });
    });

}).on('error', err => {
        if(responseSent)  return;
        responseSent = true;
        reject(err);
    });
  });

}



const readit = async () => {

await writeit();

var readandhex = fs.createReadStream(dest).pipe(crypto.createHash('sha256').setEncoding('hex'))
try {
  readandhex.on('finish', function () {       //MAY BE PROBLEM IS HERE.
    console.log(this.read())
    fs.unlink(dest, () => {});
   })
}
catch (err) {
    console.log(err);
    return err;
}
}



const handler = async() =>{                  //Comment this line to run the code on AWS Lambda
//exports.handler = async (event) => {       //UNComment this line to run the code on AWS Lambda
    try {
        hexData = readit();
    }
    catch (err) {
        console.log(err);
        return err;
    }
    return hexData;
};



handler()                                   //Comment this line to run the code on AWS Lambda

您可能需要检查多项内容。

  1. 因为,您正在访问的 URL 是公共的,请确保您的 lambda 在 VPC 之外,或者您的 VPC 具有与 inte.net 访问相连的 NAT 网关。

  2. /tmp是 lambda 的有效临时目录,但您可能需要在使用前在/tmp中创建doc文件夹。

您可以检查云监视日志以获取有关启用后发生的情况的更多信息。

我之前已经看到本地和 lambda 之间的这种行为差异。

所有异步函数都返回承诺。 必须等待异步函数。 调用异步 function 而不等待它意味着执行继续到下一行,并且可能超出调用 function。

所以你的代码:

exports.handler = async (event) => {
    try {
        hexData = readit();
    }
    catch (err) {
        console.log(err);
        return err;
    }
    return hexData;
};

readit()被定义为const readit = async () => {... } 但是您的处理程序不会等待它。 因此hexData = readit(); 将未解析的 promise 分配给hexData ,返回它,并且处理程序退出并且 Lambda “完成”而没有执行readit()的代码。

简单的解决方法是等待异步 function: hexData = await readit(); . 它在节点本地工作的原因是因为节点进程将在退出之前等待承诺解决,即使处理程序 function 已经返回。 但由于 Lambda 在处理程序返回后立即“返回”,未解决的承诺仍未解决。 (顺便说一句,不需要将writeit function 标记为异步,因为它不等待任何东西,并且已经返回 promise。)

话虽这么说,我不太了解承诺,而且我对事件几乎一无所知。 所以还有其他一些事情会为我发出警告标志,但我不确定它们,也许它们非常好,但我会在这里提出它以防万一:

file.on('finish'readandhex.on('finish' 。这些都是事件,我相信它们是非阻塞的,那么为什么处理程序和 lambda 会等待它们?

在第一种情况下,它在 promise 中并且从事件 function 中调用resolve() ,所以这可能没问题(正如我所说,我对这两个主题了解不多,所以不确定) - 重要的是是代码必须在那个点阻塞,直到 promise 被解决。 如果代码可以继续执行(即从writeit()返回)直到引发finish事件,那么它就不会工作。

第二种情况几乎肯定会成为问题,因为它只是说如果引发 x 事件,执行 y。 没有等待 promise,所以没有什么可以阻止代码,所以它会愉快地继续到readit() function 的末尾,然后是处理程序和 lambda。同样,这是基于事件是非阻塞的假设(在某种意义上的,一个你想在某个事件上执行一些代码的声明,不会在那个时候等待那个事件被引发)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM