node.js - Puppeteer 在 Linux 上的 Azure Functions Node 上部署时引发启动异常

标签 node.js azure azure-functions puppeteer azure-functions-runtime

问题:使用 puppeteer 获取网站的屏幕截图。在开发计算机上运行良好,但在部署到云上的 Azure Functions 时抛出以下异常。

环境:在 Azure 上( Node 12、Linux、消费计划),使用服务总线主题触发的函数。

错误:

Result: Failure Exception: Error: Failed to launch the browser process! spawn 
/home/site/wwwroot/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome 
EACCES TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md 
Stack: Error: Failed to launch the browser process! 
spawn /home/site/wwwroot/node_modules/puppeteer/.local-chromium/linux-818858/chrome-linux/chrome 
EACCES TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md 
at onClose (/home/site/wwwroot/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserRunner.js:193:20) 
at ChildProcess.<anonymous> (/home/site/wwwroot/node_modules/puppeteer/lib/cjs/puppeteer/node/BrowserRunner.js:185:85)
at ChildProcess.emit (events.js:314:20) at Process.ChildProcess._handle.onexit (internal/child_process.js:274:12)
at onErrorNT (internal/child_process.js:470:16) at processTicksAndRejections (internal/process/task_queues.js:84:21)

我按照 puppeteer 故障排除文档中的建议进行操作,但仍然遇到相同的问题。

我尝试过的午餐设置

let browser = await puppeteer.launch({ ignoreDefaultArgs: ['--disable-extensions'] });

let browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] });

let browser = await puppeteer.launch({ headless: true });   

let browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });

以上方法均无效。他们都抛出相同的错误。

我检查了 FTPing 功能,puppeteer 正在寻找的 chrome 文件存在。

提前致谢。

最佳答案

Azure 具有在 Linux 消费计划中运行 headless Chromium 所需的依赖项。因此我们可以在Azure函数中使用puppeteer包。但我们需要使用远程构建来部署应用程序。更多详情请引用Azure feedbackblog .

例如

  1. 创建 Azure 函数应用 enter image description here

  2. 创建 Azure 函数项目

a.安装包

  npm install puppeteer

b.函数.json

{
  "bindings": [
    {
      "name": "mySbMsg",
      "type": "serviceBusTrigger",
      "direction": "in",
      "topicName": "bowman1012",
      "subscriptionName": "test",
      "connection": "bowman1012_SERVICEBUS"
    },
    {
      "type": "blob",
      "direction": "out",
      "name": "outputBlob",
      "path": "outcontainer/{rand-guid}.png",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

c.代码

const puppeteer = require("puppeteer");

module.exports = async function (context, mySbMsg) {
  context.log(
    "JavaScript ServiceBus topic trigger function processed message",
    mySbMsg
  );
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto("https://google.com/");
  const screenshotBuffer = await page.screenshot({ fullPage: true });
  await browser.close();
  context.bindings.outputBlob = screenshotBuffer;
};

  • 在根项目文件夹中添加.funcignore文件
  • *.js.map
    *.ts
    .git*
    .vscode
    local.settings.json
    test
    tsconfig.json
    node_modules
    
  • 部署到 Azure
  • func azure functionapp publish $appName --build remote
    
  • 测试 enter image description here enter image description here
  • <小时/>

    更新

    由于您使用 typescript 创建 Azure 函数,因此我们需要更新 .funcignore 如下

    *.js.map
    .git*
    .vscode
    local.settings.json
    test
    node_modules
    

    例如

    我的函数代码index.ts

    import { AzureFunction, Context } from "@azure/functions";
    import { ServiceBusMessage } from "@azure/service-bus";
    import puppeteer from "puppeteer";
    import { BlobServiceClient } from "@azure/storage-blob";
    
    const serviceBusTopicTrigger: AzureFunction = async function (
      context: Context,
      mySbMsg: ServiceBusMessage
    ): Promise<void> {
      try {
        const promotionId = context.bindingData.userProperties.promotionId;
        context.log(
          "Player Screen Grabber ServiceBus topic trigger function processing message started",
          promotionId
        );
        const playerURL = "https://www.google.com/";
        let browser = await puppeteer.launch({ headless: true });
        let page = await browser.newPage();
        await page.goto(playerURL, { waitUntil: "networkidle2" });
        await page.setViewport({ width: 1920, height: 1080 });
        const screenshotBuffer = await page.screenshot({
          encoding: "binary",
        });
        await page.close();
        await browser.close();
        // the storage account connection string
        const constr = process.env["AzureWebJobsStorage"] + "";
        const blobserviceClient = BlobServiceClient.fromConnectionString(constr);
        const containerClient = blobserviceClient.getContainerClient(
          "outcontainer"
        );
        const blob = containerClient.getBlockBlobClient(`${promotionId}.png`);
        await blob.uploadData(screenshotBuffer);
        context.log(
          "Player Screen Grabber ServiceBus topic trigger function processing message ended",
          promotionId
        );
      } catch (error) {
        throw error;
      }
    };
    
    export default serviceBusTopicTrigger;
    
    

    部署到 Azure

    func azure functionapp publish $appName --build remote
    

    测试

    我的服务总线消息 enter image description here

    结果 enter image description here enter image description here

    关于node.js - Puppeteer 在 Linux 上的 Azure Functions Node 上部署时引发启动异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65609204/

    相关文章:

    node.js - 如何编写 Firebase Cloud Messaging 函数来发送推送通知

    node.js - Node + Express : loadtest causing the application to quit with Error: accept ENFILE

    azure - 需要启动虚拟机排除特定虚拟机

    c# - 模式匹配 blob 名称到具有输入绑定(bind)的函数变量

    c# - Azure 函数忽略的functions.json graphToken 绑定(bind)

    javascript - ExpressJS源代码中的 'createApplication()'函数是如何工作的?

    node.js - 通过在 Mongodb 中应用条件,使用 $find 查询嵌套对象

    azure - 有没有办法动态确定 vhdSize 标志?

    c# - 如何在 Azure 中运行安全的 Service Fabric 有状态服务?

    azure - 监视本地 Azure Functions?