2020-07-19に投稿

puppeteer-clusterでpuppeteerの同時起動数制御

経緯

OGP生成用のpuppeteerアプリケーションに複数アクセスがあった場合、同時にpuppeteerが複数起動してしまってサーバのリソースを食い尽くす憂き目に遭ったのでpuppeteer-clusterを使って同時起動数を制御することにした。

puppeteer-cluster

github

maxConcurrency

同時に起動する最大プロセス数です。

puppeteerOptions

puppeteerに渡していたオプションがclusterでも使えます。

        headless: true,
        executablePath: "/usr/bin/chromium-browser",
        args: ["--no-sandbox"],

cluster.execute()

結果を取得するためにqueueではなくexecuteを使います。

実装

try {
    const cluster = await Cluster.launch({
      concurrency: Cluster.CONCURRENCY_CONTEXT,
      //同時最大起動数1
      maxConcurrency: 1,
      //puppeteerの起動オプション
      puppeteerOptions: {
        headless: true,
        executablePath: "/usr/bin/chromium-browser",
        args: ["--no-sandbox"],
      },
    });
    await cluster.task(async ({ page, data: id }) => {
      await page.goto("https://cap-baseball.com/player/" + id);
      await page.setCacheEnabled(false);
      await page.waitForSelector("#main");
      const fullPage = await page.$("#main");
      const fullPageSize = await fullPage.boundingBox();
      const VIEWPORT = { width: 920, height: 700, deviceScaleFactor: 1 };
      await page.setViewport(
        Object.assign({}, VIEWPORT, { height: fullPageSize.height })
      );
      await page.waitFor(3000);

      const elements = await page.$$("#main");
      let img;
      for (const [index, element] of elements.entries()) {
        img = await element.screenshot();
      }
      await page.close();
      await console.log("screenshot done.");
      //撮ったスクリーンショットを返却する
      return img;
    });
    //結果を取得するためにqueueではなくexecuteを使う
    const result = await cluster.execute(capId);
    await cluster.idle();
    await cluster.close();
    return result;
  } catch (err) {
    console.error(err);
    throw new Error(err);
  }

ckoshien

個人開発5年目。普段はフロントエンドエンジニア。 ReactJS/NextJS/NodeJS/ReactNative/Java

所有者限定モードのためこのボードには投稿できません
コメント