【问题标题】:Long Running App Engine Script "Quitting on terminated signal"长时间运行的 App Engine 脚本“在终止信号时退出”
【发布时间】:2020-07-06 06:22:47
【问题描述】:

我正在尝试通过应用引擎运行几个长时间运行的脚本。我是初学者,这是我第一个使用 App Engine 和 express 的项目。

我在 Node 中使用 express 处理请求。

当我(或 cron 作业)向我的任何端点发送请求时,脚本似乎运行良好,直到随机点〜 5-10 分钟后我得到以下日志:

  1. 项目收到“/_ah/stop”请求
  2. “终止信号时退出”消息
  3. “启动程序失败:用户应用程序失败,退出代码为 -1(有关详细信息,请参阅 stdout/stderr 日志):信号:终止”

我不知道为什么会这样。

我的 app.yaml:

runtime: nodejs10
instance_class: B2
basic_scaling:
  max_instances: 25
  idle_timeout: 12m

请求处理程序代码:

app.get("/longRunningFunctionOne", async (req, res) => {
    await longRunningFunctionOne();
    res.send("DONE");
});

app.get("/longRunningFunctionTwo", async (req, res) => {
    await longRunningFunctionTwo();
    res.send("DONE");
});

app.get("/_ah/start", async (req, res) => {
    res.sendStatus(200);
});

在本地运行时绝对没有问题。知道我在做什么来获得过早的 /_ah/stop 请求吗?因为我使用的是基本缩放,所以我不会超时。谷歌将其描述为:

“HTTP 请求和任务队列任务 24 小时。如果您的应用未在此时间限制内返回请求,App Engine 会中断请求处理程序并发出错误以供您的代码处理。”

有什么想法吗?也许与我处理 /_ah/start 的方式有关,这只是在黑暗中拍摄?

【问题讨论】:

  • 如何称呼您的端点?您之前是否已经使用自动扩展进行部署?
  • 我尝试在浏览器中或通过 cron 调用它。都不工作。最初它是通过自动扩展部署的,但我现在已经使用 app.yaml 将其更改为基本,您可以在上面看到。难道是因为 /_ah/start 处理程序立即返回响应,24 小时请求超时将不适用于我的函数端点并且实例在 12m 空闲超时后关闭?
  • 我已检查内存使用是否是问题所在,可以排除。
  • 不,开始端点应该没有问题。你确定之前版本的所有实例都停止了吗?
  • 我会定期删除以前的版本,因此可以肯定情况并非如此。 /_ah/start 和 /_ah/stop 请求之间的时间始终为 12 分钟,这让我认为这是空闲超时的问题(在我的 app.yaml 中设置为“idle_timeout: 12m”)。跨度>

标签: node.js express google-app-engine google-cloud-platform timeout


【解决方案1】:

我发现,由于我向应用程序发送非常不频繁的请求,我在脚本完成之前遇到了实例空闲超时/

因此,即使任务仍在应用程序上运行,因为它在过去约 15 分钟内没有收到 http 请求,它也会发送 /_ah/stop 请求并关闭实例。

为了在脚本运行时保持实例处于活动状态,我创建了一个函数,该函数每分钟向应用发送一个请求以使其保持运行,并且不会达到空闲超时。

我称之为Beegees“活着”功能:

const appUrl = "https://myurl.appspot.com/";

app.get("/script1", async (req, res) => {
    res.send("running script 1");
    stayAlive(script1);
});

app.get("/script2", async (req, res) => {
    res.send("running script 2");
    stayAlive(script2);
});

app.get("/", async (req, res) => {
    res.send(" ");
});

app.listen(process.env.PORT || 4000, () => {
  console.log(`Listening on port ${process.env.PORT || 4000}`);
});

const stayAlive = async (mainAsyncFunc) => {
  const intervalId = setInterval(sendAppRequest, 60000);
  await mainAsyncFunc();
  clearInterval(intervalId);
};

const sendAppRequest = () => {
  console.log("Stayin alive");
  axios.get(appUrl);
};

看起来有点奇怪,但它确实有效。如果您知道更好的方法,请告诉我。

【讨论】:

  • 我也遇到了类似的“问题”,并最终安排了运行以每 5 分钟调用一次 keepalive 端点。希望有更好的方式来表示 GAE 不会杀死应用程序
  • 我喜欢你的想法,对实际解决方案有任何更新吗?
  • 是的,我面临着同样的问题@Dan Williams。你能帮忙吗?
  • 视情况而定,您可以考虑使用 Cloud Tasks。 cloud.google.com/tasks/docs
猜你喜欢
  • 2016-03-25
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-01
相关资源
最近更新 更多