【问题标题】:When will memory get freed after completing the request on App Engine Backend Instances?完成对 App Engine 后端实例的请求后,何时会释放内存?
【发布时间】:2017-12-15 01:35:00
【问题描述】:

场景-

我在 App Engine 上运行 B* 实例。我有一个后台 ETL 相关任务(用 python 编写)安排为 App Engine 上的 cron 作业。 当时间到达时,cron 发起一个 http 请求来启动任务并运行而不返回响应,直到任务完成。 当任务执行时,它通常会消耗“X”MB 的 RAM。任务完成并返回 200 OK 后,App Engine 实例监控仍显示“X”MB 的 RAM 正在使用中。

请帮助我理解以下内容-

  1. 如果一个实例只运行一个任务,并且在完成它之后,该任务消耗的内存何时会被释放?
  2. 是否需要运行 gc.collect() 来显式调用垃圾收集器以释放 RAM?
  3. 释放 RAM 的唯一方法是重新启动实例?

PS:这与 NDB 完全无关,我的任务是从 Bigquery 获取输入,执行一些 ETL 操作,然后将其流式传输到 Bigquery。

【问题讨论】:

    标签: google-app-engine google-app-engine-python


    【解决方案1】:

    根据我对使用大量内存进行StringIO 操作的应用的观察:

    • 显式调用 gc.collect() 并没有明显帮助(我什至怀疑我确实有内存泄漏,但事实并非如此)

    • 内存不会在每次请求后释放,但是,如果实例保持活动的时间足够长而没有耗尽内存,它最终会 似乎不时被释放。易于测试 - 只需增加请求之间的时间以降低可用内存耗尽率。但我想不出一个可用的模式。请注意,我仅在升级到 B2 实例后才观察到这一点,我的 B1 实例内存不足过快,我从未注意到它们有释放事件。

    • 使用具有更多内存的instance class(我尝试作为我的实例最终耗尽内存的解决方法)有所帮助 - 内存似乎更频繁地被释放。 可能是因为这些实例也有更快的 CPU(但这只是猜测)。

    【讨论】:

    • 您提到的第二点似乎有时有效。我增加了请求之间的延迟,现在我看到内存不时被释放。
    • @AnkurChoraywal 除了增加请求之间的延迟之外,您是否找到了解决方案。我也想知道这是否特定于 App Engine。例如,在 Cloud Run 上会出现相同的行为吗?
    • @BrainPermafrost 在我的场景中,我通过减少从 BigQuery 查询的批量大小来解决这个问题。在 HTTP 处理程序中处理小批量,然后使用具有查询偏移量的任务队列重新调用相同的 HTTP 处理程序。这有助于将内存中断问题减少 95%
    【解决方案2】:

    StackOverflow 上有几个问题描述了在应用引擎上使用 ndb 时任务的类似内存问题。这是一个example

    问题是应用引擎在任务结束时不会清除 ndb 上下文缓存,因此上下文缓存会在任务完成后很长时间内继续占用您的内存。

    解决方案是在您的任务期间不使用或清除上下文缓存。这里有几种方法:

    • 使用key.get(use_cache=False)绕过缓存
    • 在适当的时候致电ndb.get_context().clear_cache()
    • 通过将_use_cache = False 添加到您的模型定义中来禁用所有实体的缓存。

    【讨论】:

    • 在这个bug report中有广泛的讨论。
    • 谢谢杰夫!但这与 NDB 完全无关。我正在运行一个从 BIGQUERY 获取输入数据的任务,对这些数据执行一些 ETL 操作,然后将其流式传输到 BIGQUERY,然后任务完成。你能告诉我完成任务后我们如何释放内存吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-06
    • 2011-03-25
    • 1970-01-01
    • 2013-07-02
    • 2012-07-04
    • 1970-01-01
    • 2023-04-04
    相关资源
    最近更新 更多