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 总是超时的主要内容,如果未能解决你的问题,请参考以下文章