而不是本地时获取调用出现 503 错误"/>
部署到 heroku 而不是本地时获取调用出现 503 错误
问题: 当我在部署到 heroku 后向我的服务器发送特定的 get 请求时,我每次都会收到 503 错误,并且应用程序没有完成我期望的提交操作。该请求专门用于触发 puppeteer 屏幕截图代码并将带有屏幕截图的 zip 文件返回给客户端。这在本地按预期完美运行,只有在部署后才会失败。
值得注意的错误: 我的 heroku 日志在屏幕截图的一半左右产生请求超时错误,代码是 H12。我现在还不清楚造成这种情况的原因是什么,因此解决方案应该是什么(或者甚至如何最好地找出答案)。
应用程序: 我已经构建了一个内部团队应用程序,它接受一个 url,截取该 url 上的所有横幅,然后将它们捆绑在一个 zip 文件中,并将该文件返回给客户端以供下载。
前端代码:
fetch(`/dcsgrab?tearsheetUrl=${screenShotData}`)
.then((response) => response.json())
.then((data) => {
zipBlob = new Blob([new Uint8Array(data.zipFile.data)], {type: "octet/stream"});
url = window.URL.createObjectURL(zipBlob);
zipDownload = document.createElement("a");
setMessageData(data.message);
setZipData(zipBlob);
zipDownload.href = url;
zipDownload.download = "screenshot-download.zip";
document.body.appendChild(zipDownload);
zipDownload.click();
});
};
后端代码:
app.get('/dcsgrab', (request, response) => {
const zip = new AdmZip();
(async () => {
const browser = await puppeteer.launch({
headless: true,
executablePath: executablePath(),
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--single-process',
],
});
let screenshotCounter = 1;
const page = await browser.newPage();
page.setViewport({width: 1280, height: 6000, deviceScaleFactor: PIXEL_DENSITY});
await page.goto(request.query.tearsheetUrl, { waitUntil: 'networkidle0' });
/**
* Checks if the pagination button is active
* @return {Promise.<Boolean>} Promise which resolves with a true boolean if the button is active
*/
async function isNextButtonActive() {
return await page.evaluate((selector) => {
return !document.querySelector(selector).disabled;
}, NEXT_SELECTOR);
}
/**
* Clicks the pagination button
* @return {Promise} Promise which resolves when the element matching selector is successfully clicked. The Promise will be rejected if there is no element matching selector
*/
async function clickNextButton() {
return await page.click(NEXT_SELECTOR, {delay: 100});
}
/**
* Waits for the loading spinner widget to go away, indicating the iframes have been added to the page
* @return {Promise.undefined}
*/
async function waitForLoadingWidget() {
return await page.waitForSelector('.preview-loading-widget', {hidden: true}).then(() => {
console.log('Loading widget is gone');
})
.catch(e => {
console.log(e.message);
});
}
/**
* Screenshot the creative elements on the current page
* @return {Promise.<Array>} Promise which resolves with an array of clipping paths
*/
async function getScreenShots() {
const rects = await page.$$eval(PREVIEW_SELECTOR, iframes => {
return Array.from(iframes, (el) => {
const {x, y, width, height} = el.getBoundingClientRect();
return {
left: x,
top: y,
width,
height,
id: el.id,
};
});
}, PREVIEW_SELECTOR).catch(e => {
console.error(e.message);
});
return Promise.all(rects.map(async (rect) => {
return await page.screenshot({
clip: {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height,
},
}).then((content) => {
zip.addFile(`screenshot-${screenshotCounter++}.png`, Buffer.from(content, "utf8"), `screenshot ${screenshotCounter++} saved`);
console.log(`${rect.id} element captured and stored in zip`);
})
.catch((e) => {
console.error(e.message);
});
}));
}
// Wait a bit then take screenshots
await new Promise(resolve => setTimeout(resolve, DELAY_FOR_ANIMATION));
await getScreenShots().catch((e) => console.error(e.message));
// Continue taking screenshots till there are no pages left
while (await isNextButtonActive()) {
await clickNextButton();
await waitForLoadingWidget();
await new Promise(resolve => setTimeout(resolve, DELAY_FOR_ANIMATION)),
await getScreenShots().catch((e) => console.error(e.message));
}
await browser.close();
const zipToSend = zip.toBuffer();
response.json({
message: 'Screenshots are done!\nPlease check the zip file that was just downloaded.',
zipFile: zipToSend
});
})();
});
Heroku 日志:
2023-03-23T19:27:43.174105+00:00 heroku[web.1]: Restarting
2023-03-23T19:27:43.189825+00:00 heroku[web.1]: State changed from up to starting
2023-03-23T19:27:44.190045+00:00 heroku[web.1]: Stopping all processes with SIGTERM
2023-03-23T19:27:44.368177+00:00 heroku[web.1]: Process exited with status 143
2023-03-23T19:27:53.000000+00:00 app[api]: Build succeeded
2023-03-23T19:28:07.523862+00:00 heroku[web.1]: Starting process with command `npm start`
2023-03-23T19:28:09.144631+00:00 app[web.1]:
2023-03-23T19:28:09.144660+00:00 app[web.1]: > [email protected] start
2023-03-23T19:28:09.144661+00:00 app[web.1]: > node server/server.js
2023-03-23T19:28:09.144661+00:00 app[web.1]:
2023-03-23T19:28:09.428387+00:00 app[web.1]: Server is listening on port 21309
2023-03-23T19:28:09.838525+00:00 heroku[web.1]: State changed from starting to up
2023-03-23T19:28:10.596907+00:00 heroku[router]: at=info method=GET path="/" host=dcsgrab.herokuapp request_id=f0b15bcd-7eb4-4028-b5a9-2a6f76496c05 fwd="24.16.69.155" dyno=web.1 connect=0ms service=86ms status=200 bytes=944 protocol=https
2023-03-23T19:28:10.699774+00:00 heroku[router]: at=info method=GET path="/static/js/main.1910c761.js" host=dcsgrab.herokuapp request_id=e775658f-f56d-4db8-bcb2-71de15b0d87d fwd="24.16.69.155" dyno=web.1 connect=0ms service=4ms status=200 bytes=218121 protocol=https
2023-03-23T19:28:11.706348+00:00 heroku[router]: at=info method=GET path="/static/css/main.69947f1d.css" host=dcsgrab.herokuapp request_id=5340c5b9-b516-4a5a-99f5-851b421b1949 fwd="24.16.69.155" dyno=web.1 connect=0ms service=1ms status=200 bytes=3167 protocol=https
2023-03-23T19:28:11.818395+00:00 heroku[router]: at=info method=GET path="/static/css/main.69947f1d.css.map" host=dcsgrab.herokuapp request_id=ffcf15de-1af4-4dee-83d1-99c0c811c73f fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=5370 protocol=https
2023-03-23T19:28:11.820299+00:00 heroku[router]: at=info method=GET path="/static/js/main.1910c761.js.map" host=dcsgrab.herokuapp request_id=e7c588ad-c085-4a12-bd1b-d3c4433d48de fwd="24.16.69.155" dyno=web.1 connect=0ms service=5ms status=200 bytes=746644 protocol=https
2023-03-23T19:28:11.907618+00:00 heroku[router]: at=info method=GET path="/static/media/essence_mediacom_logo-nobg-color_corrected.764800408369a0f7cf88.png" host=dcsgrab.herokuapp request_id=f1f5ed8c-eda8-46a1-af0f-8e87e8d2d615 fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=16759 protocol=https
2023-03-23T19:28:11.993490+00:00 heroku[router]: at=info method=GET path="/static/media/essencemediacom_icon.a48332799f21c2163415.png" host=dcsgrab.herokuapp request_id=05b087a5-cccc-4efb-9da4-d4b9ae3af678 fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=14971 protocol=https
2023-03-23T19:28:12.189730+00:00 heroku[router]: at=info method=GET path="/essencemediacom_icon.png" host=dcsgrab.herokuapp request_id=5921b175-24b7-43ef-8db8-1a3df51588ad fwd="24.16.69.155" dyno=web.1 connect=0ms service=2ms status=200 bytes=14971 protocol=https
2023-03-23T19:28:12.473057+00:00 heroku[router]: at=info method=GET path="/manifest.json" host=dcsgrab.herokuapp request_id=bfa7629b-b6ad-49c1-a4a0-bffb968bfbb6 fwd="24.16.69.155" dyno=web.1 connect=0ms service=1ms status=200 bytes=787 protocol=https
2023-03-23T19:28:12.555689+00:00 heroku[router]: at=info method=GET path="/logo192.png" host=dcsgrab.herokuapp request_id=174be88c-84fd-4046-8862-35c77bcef675 fwd="24.16.69.155" dyno=web.1 connect=0ms service=1ms status=200 bytes=5622 protocol=https
2023-03-23T19:28:38.626764+00:00 app[web.1]: safe-frame-1 element captured and stored in zip
2023-03-23T19:28:39.116534+00:00 app[web.1]: safe-frame-5 element captured and stored in zip
2023-03-23T19:28:39.497607+00:00 app[web.1]: safe-frame-2 element captured and stored in zip
2023-03-23T19:28:39.954761+00:00 app[web.1]: safe-frame-4 element captured and stored in zip
2023-03-23T19:28:40.270808+00:00 app[web.1]: safe-frame-3 element captured and stored in zip
2023-03-23T19:28:41.373398+00:00 app[web.1]: Loading widget is gone
2023-03-23T19:28:47.380186+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/dcsgrab?tearsheetUrl=" host=dcsgrab.herokuapp request_id=8d21b818-58e6-4f76-bd08-2d00050801b4 fwd="24.16.69.155" dyno=web.1 connect=0ms service=30000ms status=503 bytes=0 protocol=https
2023-03-23T19:28:56.769792+00:00 app[web.1]: safe-frame-8 element captured and stored in zip
2023-03-23T19:28:57.162674+00:00 app[web.1]: safe-frame-7 element captured and stored in zip
2023-03-23T19:28:57.598963+00:00 app[web.1]: safe-frame-6 element captured and stored in zip
2023-03-23T19:28:57.985009+00:00 app[web.1]: safe-frame-9 element captured and stored in zip
2023-03-23T19:28:58.436801+00:00 app[web.1]: safe-frame-10 element captured and stored in zip
2023-03-23T19:28:58.884653+00:00 app[web.1]: Loading widget is gone
回答如下:
查看官方 Heroku 错误代码 H12 它说:
一个 HTTP 请求需要超过 30 秒才能完成
因此您的服务器可能无法在 30 秒内生成响应以命中端点
/dcsgrab
,因此 Heroku 生成了错误。
更多推荐
部署到 heroku 而不是本地时获取调用出现 503 错误
发布评论