AWS Lambda 上的 PhantomJS 总是超时

Posted

技术标签:

【中文标题】AWS Lambda 上的 PhantomJS 总是超时【英文标题】:PhantomJS on AWS Lambda Always Timeout 【发布时间】:2017-07-20 11:24:24 【问题描述】:

我正在尝试在 AWS Lambda 上创建一个任务,从 PhantomJS 创建 PDF 文件,然后稍后将其上传到 AWS S3。

现在,我尝试在 Lambda 上运行它,但它总是超时。

我的 Lambda 有 128mb 的内存。运行时是 node.js 4.4.3。

这是我从 Lambda 得到的错误

"errorMessage": "2017-03-01T08:05:56.255Z dfd4cfe8-fe55-11e6-bf24-e7edf412e037 Task timed out after 10.00 seconds"

这些也是日志输出

REPORT RequestId: dfd4cfe8-fe55-11e6-bf24-e7edf412e037  Duration: 10000.08 ms   Billed Duration: 10000 ms   Memory Size: 128 MB Max Memory Used: 29 MB


2017-03-01T08:05:56.255Z dfd4cfe8-fe55-11e6-bf24-e7edf412e037 Task timed out after 10.00 seconds

这是我的代码。

Index.js

var childProcess = require('child_process');
var path = require('path');

exports.handler = function(event, context, callback) 

     // Set the path as described here: https://aws.amazon.com/blogs/compute/running-executables-in-aws-lambda/
process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];

     // Set the path to the phantomjs binary
     var phantomPath = path.join(__dirname, 'phantomjs_linux-x86_64');

     // Arguments for the phantom script
    var processArgs = [
         path.join(__dirname, 'phantom-script.js'),
         event.url
    ];

    // Launc the child process
    childProcess.execFile(phantomPath, processArgs, function(error, stdout, stderr) 
        if (error) 
            context.fail(error);
            return;
        
        if (stderr) 
            context.fail(error);
            return;
        
        context.succeed(stdout);
    );

phantom-script.js

 var system = require('system');
 var args = system.args;

 // Example of how to get arguments passed from node script
 // args[0] would be this file's name: phantom-script.js

 const url = "https://google.com";

 system.stdout.write('hello from phantom!');

 console.log("task start, target url = " + url);

 console.time("execute time");
 phantom.create().then(function(ph) 
     console.time("create Page");
     ph.createPage().then(function(page) 
         console.timeEnd("create Page");
         console.time("open website");
         page.open(url).then(function(status) 
             console.timeEnd("open website");
             console.time("render as pdf");
             page.render('google.pdf').then(function() 
                 console.timeEnd("render as pdf");
                 console.log('Page Rendered');
                 ph.exit();

                 // send to s3
                 console.timeEnd("execute time");
             );
         );
     );
 );


 // Send some info node's childProcess' stdout
 system.stdout.write('hello from phantom!')

 phantom.exit();

我尝试按照answer 做我的工作,但它不起作用。

我没有从我的phantom-script.js 获得任何日志,就像它不是触发器一样,但我的任务总是超时。

【问题讨论】:

我处于类似情况,将页面渲染为图像,并且在尝试 page.render 后似乎超时。相同的记忆,30秒。你有什么发现吗? 实际上,只是尝试在我的代码的不同部分使用 context.getRemainingTimeinMillis() ,看看我是否真的“适当地”超时了。很长一段时间后,我意识到我只是用 phantomjs 达到了最大内存,所以我翻了一番,达到 256mb。 @svjacob 我在下面的答案中添加了适合我的解决方案。这对我来说是工作。希望对您有所帮助。 【参考方案1】:

在我花了很多时间之后。我找到了包名Phantomjs-Prebuilt,您可以通过npm 安装它。您必须在具有节点版本 4.x(lambda 使用节点版本 4.3)的 amazon linux 实例或 docker amazon linux 上执行 npm install。否则它将无法在 lambda 上运行。

然后,我像这样更新了我的代码。

Index.js

var phantomjs = require('phantomjs-prebuilt')

exports.handler = function(event, context, callback) 
    var sourceUrl = "https://example.com"
    var program = phantomjs.exec('phantom-script.js', sourceUrl)
    program.stdout.pipe(process.stdout)
    program.stderr.pipe(process.stderr)
    program.on('exit', code => 
        // do something here after you phantomjs finish.
        return
    )

phantom-script.js

var system = require('system')
var args = system.args

// Example of how to get arguments passed from node script
// args[0] would be this file's name: phantom-script.js

var url = args[1] // received sourceUrl value

// Send some info node's childProcess' stdout
system.stdout.write('phantomJS running\r\n')

var webpage = require('webpage').create()

webpage.paperSize = 
    format: 'A4',
    orientation: 'landscape'


webpage.open(url, function(status) 
    system.stdout.write('start open page\r\n')
    webpage.render('/tmp/web.pdf', 
        format: 'pdf',
        quality: '100'
    )
    system.stdout.write('finish render page\r\n')
    phantom.exit()
)

在 lambda 上,您可以写入文件的位置是 /tmp 文件夹,这就是我将文件保存在那里的原因。

我通过 lambda 运行它,内存为 192mb。它的工作真的很好。我可以使用此设置创建包含 500 张图像的网页截图。最重要的是确保您的 lambda 能够连接互联网。

仅供参考,我意识到当 phantom-script.js(我在其中编写幻像脚本的文件)出现错误时,您的 lambda 将冻结直到超时。这就是为什么我总是收到来自 lambda Task timed out after 10.00 seconds 的回复。

【讨论】:

以上是关于AWS Lambda 上的 PhantomJS 总是超时的主要内容,如果未能解决你的问题,请参考以下文章

无法让phantomjs在aws lambda上工作

aws lambda 上的保留并发不会阻止 lambda 进行更多扩展?

schedult 上的 aws 自定义事件以触发 lambda 使用 Terraform

是啥导致 AWS Lambda 上的 Mongodb 超时错误?

AWS 事件总线无法将日志写入来自 AWS Lambda 的自定义日志组上的 CloudWatch

AWS Lambda:提供的执行角色无权调用 EC2 上的 DescribeNetworkInterfaces