【问题标题】:Why do processes running on Google App Engine hang?为什么在 Google App Engine 上运行的进程会挂起?
【发布时间】:2016-01-22 17:10:05
【问题描述】:

我们有一个 cron 作业,它每小时在后端模块上运行并创建任务。 cron 作业在 Cloud SQL 数据库上运行查询,任务向其他服务器发出 HTTP 调用并更新数据库。通常它们运行良好,即使创建了数千个任务,但有时它会“卡住”并且日志中没有任何内容可以说明情况。 例如,昨天我们监控了 cron 作业,它创建了几十个任务然后它停止了,还有 8 个任务也卡在队列中。当很明显没有发生任何事情时,我们又运行了几次该过程,每次都成功完成。

一天后,原始任务被 DeadlineExceededException 杀死,然后显然在同一实例中运行的其他 8 个任务被杀死并显示以下消息: 处理此请求的进程遇到问题,导致它退出。这可能会导致一个新进程被用于对您的应用程序的下一个请求。如果您经常看到此消息,则可能是在应用程序初始化期间引发了异常。 (错误代码 104)

在进程被杀死之前,我们在日志中完全没有看到它们的记录,现在我们看到它们,在 DeadlineExceededException 之前没有任何日志记录,所以我们不知道它们在什么时候卡住了。 我们怀疑数据库中存在一些锁定,但我们在以下链接中看到查询有 10 分钟的限制,这样会导致进程比一天更快地失败:https://cloud.google.com/appengine/docs/java/cloud-sql/#Java_Size_and_access_limits

我们模块的类和缩放配置是:

<instance-class>B4</instance-class>
<basic-scaling>
    <max-instances>11</max-instances>
    <idle-timeout>10m</idle-timeout>
</basic-scaling>

队列的配置是:

<rate>5/s</rate>
<max-concurrent-requests>100</max-concurrent-requests>
<mode>push</mode>
<retry-parameters>
    <task-retry-limit>5</task-retry-limit>
    <min-backoff-seconds>10</min-backoff-seconds>
    <max-backoff-seconds>200</max-backoff-seconds>
</retry-parameters>

我为 cron 作业上传了一些跟踪数据的图像: http://imgur.com/a/H5wGG。 这包括跟踪摘要和时间线的开始/结束。 8 个终止的任务没有跟踪数据。

这可能是什么原因,我们如何进一步调查?

【问题讨论】:

  • 您能否尝试启用Cloud Trace,然后包含您的慢请求之一的跟踪?
  • @David 我编辑了我的问题以包含 cron 作业的跟踪数据:imgur.com/a/H5wGG。他包括跟踪摘要和时间线的开始/结束。 8 个终止的任务没有跟踪数据。
  • 标准做法是首先隔离问题。您可以对数据库进行查询并查看查询运行需要多长时间吗?使用 Google App Engine 可能并不直接,因此您可能希望在将本地计算机的 IP 授权给 Cloud SQL 实例等之后从本地计算机运行查询。
  • 24 小时超时是因为您使用的是手动缩放。您包含的跟踪排除了一些 API 问题,但不排除云 sql(由于它不是简单的请求-响应协议,因此不会显示在跟踪中)。接下来,您可能想在进程挂起时尝试​​在 Cloud SQL 主机上“显示进程列表”,以查看它是否已连接/它在做什么。这将使我们能够确定它是否由于缓慢的 Cloud SQL 查询或死锁而挂起。
  • @David 现在有些任务已经卡了几个小时。 “SHOW PROCESSLIST”显示了 17 行,其中命令为“Sleep”,用户为“root”,主机为“localhost”。其中 8 个“时间”为 10199(2+ 小时),8 个“时间”为 8656(2+ 小时),1 个“时间”为 243(4 分钟,最后一个不断更新)。这些是“SHOW PROCESSLIST”的唯一结果,除了显示我运行此查询的记录。此服务器上没有正在处理的其他请求。

标签: java google-app-engine cron google-cloud-sql task-queue


【解决方案1】:

我们最终通过以下步骤解决了这个问题:

  1. 我们将模块拆分为两个模块 - 一个模块运行 cron 作业,另一个模块 一个模块来处理生成的任务。这让我们看到 问题在于处理任务,因为这是唯一的 一直卡住的模块。
  2. 我们将并发任务的数量限制为 2,这似乎是在系统不会卡住的情况下可以同时处理的最大任务数量。

【讨论】:

  • 您在处理任务时是否看到任何缓慢的情况,因为您将并发任务设置为 2。您在使用这种方法时还面临任何其他问题吗??
  • 我们对这种方法没有任何问题,我们发现任务的吞吐量对我们来说已经足够好了。
  • 我遇到过这个问题,我也没有一个完整的解决方案,但我发现它可能与数据库上的写争用问题有关。消除跨线程对相同对象的写入会有所帮助。
猜你喜欢
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
相关资源
最近更新 更多