完成对 App Engine 后端实例的请求后,何时会释放内存?

When will memory get freed after completing the request on App Engine Backend Instances?

场景-

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

请帮我理解以下内容-

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

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

Whosebug 上有几个问题描述了在 App Engine 上使用 ndb 时任务的类似内存问题。这是一个 example.

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

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

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

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

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

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

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