Node.js应用,带有Express,部署在Heroku上。它只是动态网页。加载静态网页可以正常工作。
加载动态网页工作在本地主机,但在Heroku它抛出我code=H12
,desc="Request timeout"
,service=30000ms
,status=503
。
此外,在执行heroku restart
或进行部署之后,似乎总是有一个status=200
的实例只加载动态网页的静态部分。
日志截图。
我尝试了以下方法,这些方法在Heroku(如Error R14 (Memory quota exceeded)
和code=H13 desc="Connection closed without response"
)上部署时都导致了相同或其他意想不到的结果:
- 切换我正在使用的木偶英雄构建包。我已经尝试了本故障排除指南和这条评论中提到的那些。
- 在Puppeteer的
launch
参数中添加headless: true
- 在Puppeteer的
launch
参数的args
中增加--no-sandbox
,--disable-setuid-sandbox
,--single-process
和--no-zygote
标志。(参考:此评论&这个评论) - 将Puppeteer的
goto
函数中的waitUntil
参数设置为domcontentloaded
、networkidle0
和networkidle2
。(参考:此评论) 在Puppeteer - 使用
waitForSelector
函数 - 清除Heroku的构建缓存,按照本文。
- 在控制台中打印
url
变量(参见下面的代码)。输出符合预期
goto
函数中传递timeout
参数;我特别尝试了30000
和60000
,以及0
。我已经观察到:
- 使用我现在拥有的代码(见下文),
try-catch-finally
块从未捕获任何错误。它总是以下之一:我得到一个不完整的结果(请求的动态网页的静态部分),或应用程序崩溃(code=H13 desc="Connection closed without response"
)。所以我没有能够从catch
块内的控制台中打印exception
中得到任何东西。
关于如何使其工作的任何想法?
const app = express();
const puppeteer = require("puppeteer");
let port = process.env.PORT || 3000;
let browser;
...
app.listen(port, async() => {
browser = await puppeteer
.launch({
timeout: 0,
headless: true,
args: [
"--no-sandbox",
"--disable-setuid-sandbox",
"--single-process",
"--no-zygote",
],
});
});
...
app.get("/appropriate-route-name", async (req, res) => {
let url = req.query.url;
let page = await browser.newPage();
try {
await page.goto(url, {
waitUntil: "networkidle2",
});
res.send({ data: await page.content() });
} catch (exception) {
res.send({ data: null });
} finally {
await browser.close();
}
}
能够通过使用user-agents
使其工作。动态页面现在在Heroku上加载得很好;请求不再每次都超时了。
const app = express();
const puppeteer = require("puppeteer");
let port = process.env.PORT || 3000;
var userAgent = require("user-agents");
...
app.get("/route-name", async (req, res) => {
let url = req.query.url;
let browser = await puppeteer.launch({
args: ["--no-sandbox"],
});
let page = await browser.newPage();
try {
await page.setUserAgent(userAgent.toString()); // added this
await page.goto(url, {
timeout: 30000,
waitUntil: "newtorkidle2", // or "networkidle0", depending on what you need
});
res.send({ data: await page.content() });
} catch (e) {
res.send({ data: null });
} finally {
await browser.close();
}
});