You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

生产环境使用Puppeteer生成PDF报504 Gateway Time-out错误如何解决

Puppeteer PDF生成生产环境504超时解决方案

常见原因及对应解决办法

1. 生产环境缺失Chrome运行依赖

无桌面的Linux服务器默认缺少Chromium运行所需的系统依赖库,本地有图形环境所以可以正常运行,生产环境启动浏览器时会卡住导致超时。
解决方法:安装对应系统的依赖包,以Debian/Ubuntu为例,执行以下命令:

apt update && apt install -y \
  gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \
  libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 \
  libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 \
  libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 \
  libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation \
  libappindicator1 libnss3 lsb-release xdg-utils wget

2. 页面加载规则过于严格导致超时

当前代码使用waitUntil: "networkidle0",要求页面500ms内没有任何网络请求才判定加载完成,如果目标页面存在轮询、长连接、持续上报的埋点请求,会一直达不到判定条件触发超时。
解决方法:调整页面加载配置,放宽判定规则同时设置最大超时时间:

// 修改page.goto配置,最多等待30秒,使用更宽松的networkidle2(允许最多2个活跃请求)
await page.goto(url, { 
  waitUntil: "networkidle2", 
  timeout: 30 * 1000 
});

3. Puppeteer启动参数缺失

无桌面环境下仅配置--no-sandbox不足以正常启动Chrome,还需要补充其他适配参数:
解决方法:调整launch配置:

const browser = await puppeteer.launch({ 
  args: [
    "--no-sandbox",
    "--disable-setuid-sandbox",
    "--disable-dev-shm-usage", // 规避/dev/shm空间不足问题
    "--disable-gpu", // 无GPU环境禁用硬件加速
    "--no-first-run",
    "--no-zygote"
  ] 
});

4. 生产环境网络连通性异常

生产服务器可能无法正常访问你传入的目标URL,比如DNS解析失败、防火墙限制出站请求、内部域名没有配置host等,导致page.goto一直卡住。
解决方法:登录生产服务器执行curl命令验证连通性:

curl https://apps.socialtools.me/preview/discount-coupon/613e0c6a9115bb003681958d/print/0

如果请求失败,排查服务器DNS、防火墙、路由规则配置。

5. 进程资源不足

如果是Docker/K8s等容器化部署,默认给的内存配额过低(低于1G),Chrome启动和渲染PDF需要占用大量内存,资源不足会触发OOM被系统kill,导致请求无响应。
解决方法:调高进程内存配额,建议至少分配1.5G以上内存。

6. 缺失错误捕获逻辑

当前代码没有异常捕获逻辑,任意步骤报错后既不会关闭浏览器也不会返回响应,会一直挂起直到网关超时。
解决方法:添加try/catch/finally逻辑,优化后的完整代码如下:

const puppeteer = require("puppeteer");
module.exports = {
  async generate(req, res) {
    let browser = null;
    try {
      let url = req.query.url;
      if (!url) return res.status(400).send('缺少url参数');
      let name = req.query.name ? req.query.name : "file";
      browser = await puppeteer.launch({ 
        args: [
          "--no-sandbox",
          "--disable-setuid-sandbox",
          "--disable-dev-shm-usage",
          "--disable-gpu",
          "--no-first-run",
          "--no-zygote"
        ] 
      });
      const page = await browser.newPage();
      await page.goto(url, { waitUntil: "networkidle2", timeout: 30 * 1000 });
      const pdf = await page.pdf({ format: "A4" });
      
      res.set({
        "Content-Type": "application/pdf",
        "Content-Length": pdf.length,
      });
      res.setHeader("Content-disposition", `attachment; filename=${encodeURIComponent(name)}.pdf`);
      res.send(pdf);
    } catch (err) {
      console.error('PDF生成失败:', err);
      res.status(500).send('PDF生成失败:' + err.message);
    } finally {
      if (browser) await browser.close();
    }
  },
};

注:代码中增加了encodeURIComponent处理文件名,避免中文或特殊字符导致的文件名乱码问题。


内容的提问来源于stack exchange,提问作者sagar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 10:06:01