【问题标题】:puppeteer-cluster: queue instead of executepuppeteer-cluster:队列而不是执行
【发布时间】:2019-08-09 22:16:31
【问题描述】:

我正在试验 Puppeteer Cluster,但我只是不明白如何正确使用队列。它只能用于您不等待响应的呼叫吗?我正在使用 Artillery 同时发出一堆请求,但它们都失败了,而当我直接执行命令时只有一些失败。

我直接从examples 获取代码并将execute 替换为我希望可以工作的queue,除了代码不等待结果。有没有办法实现这一目标?

所以这行得通:

const screen = await cluster.execute(req.query.url);

但这会中断:

const screen = await cluster.queue(req.query.url);

这是queue的完整示例:

const express = require('express');
const app = express();
const { Cluster } = require('puppeteer-cluster');

(async () => {
    const cluster = await Cluster.launch({
        concurrency: Cluster.CONCURRENCY_CONTEXT,
        maxConcurrency: 2,
    });
    await cluster.task(async ({ page, data: url }) => {
        // make a screenshot
        await page.goto('http://' + url);
        const screen = await page.screenshot();
        return screen;
    });

    // setup server
    app.get('/', async function (req, res) {
        if (!req.query.url) {
            return res.end('Please specify url like this: ?url=example.com');
        }
        try {
            const screen = await cluster.queue(req.query.url);

            // respond with image
            res.writeHead(200, {
                'Content-Type': 'image/jpg',
                'Content-Length': screen.length //variable is undefined here
            });
            res.end(screen);
        } catch (err) {
            // catch error
            res.end('Error: ' + err.message);
        }
    });

    app.listen(3000, function () {
        console.log('Screenshot server listening on port 3000.');
    });
})();

我在这里做错了什么?我真的很想使用排队,因为没有它,每个传入的请求似乎都会减慢所有其他请求的速度。

【问题讨论】:

    标签: javascript node.js puppeteer puppeteer-cluster


    【解决方案1】:

    puppeteer-cluster 的作者在这里。

    引用自文档:

    cluster.queue(..):[...] 请注意,出于向后兼容性的原因,此函数仅返回 Promise。该函数不会异步运行,会立即返回。

    cluster.execute(...):[...] 像Cluster.queue 一样工作,只是这个函数返回一个 Promise,它将在任务执行后被解析。如果在执行过程中发生错误,该函数将拒绝 Promise 并抛出错误。不会触发“taskerror”事件。

    何时使用哪个功能:

    • 如果您想将大量作业(例如 URL 列表)排队,请使用 cluster.queue。任务函数需要通过将结果打印到控制台或将它们存储到数据库来处理存储结果。
    • 如果您的任务函数返回结果,请使用cluster.execute。这仍然会将作业排队,所以这就像在等待作业完成之外调用queue。在这种情况下,通常会出现一个“空闲集群”,当请求到达服务器时会使用它(如您的示例代码中)。

    所以,你肯定想使用cluster.execute,因为你想等待任务函数的结果。您看不到任何错误的原因是(如上所述)cluster.queue 函数的错误是通过taskerror 事件发出的。直接抛出cluster.execute 错误(Promise 被拒绝)。最有可能的是,在这两种情况下,您的作业都会失败,但它仅对 cluster.execute 可见

    【讨论】:

    • 啊,我明白了,谢谢!我不知何故完全错过了那部分。只是为了清楚起见,execute 将指定的调用放入队列机制中,在该机制中集群分配工作人员,以便在任务可用时接收任务?如果是这种情况,是否将 maxConcurrency(worker 数量)设置为等于可用内核是一个坏主意,因为它可能会给服务器带来所有内核 100% cpu 使用率的负担?感谢您的时间和 puppeteer-cluster,它为我节省了数周的头痛。如果需要,我可以发布一个新问题。
    • 是的,我稍后会编辑我的问题以澄清这部分。 cluster.execute 也将作业排队。唯一的区别是阻塞(和错误处理部分)。理想情况下,您不会接近 100% 的 CPU 利用率,但这取决于您正在执行的任务和您拥有的 CPU,以及您的系统可以处理多少工作人员。请参阅this question/answer 了解更多信息。
    • @ThomasDondorf 非常有用!谢谢,我正在从 PhantomJS 迁移到 Puppeteer,并且正要制作一个 DEQUE 控制器,直到我找到你的仓库
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多