写入云存储时 GAE 内存泄漏,我可以流式传输吗?

Posted

技术标签:

【中文标题】写入云存储时 GAE 内存泄漏,我可以流式传输吗?【英文标题】:GAE Memory Leaks when writing to Cloud Storage, can I stream instead? 【发布时间】:2015-05-04 17:18:33 【问题描述】:

我正在从外部 API 请求数据,并将其直接写入云存储文件。数据写得很好,但是当我扩展时,我遇到了内存问题并达到了 GAE 实例的 1024 MB 限制。

这些是我得到的严重错误:

Exceeded soft private memory limit of 1024 MB with 1425 MB after servicing 46 requests total

这是我正在使用的代码的摘要:

import cloudstorage as gcs
import urllib2

# Example file path
filePath = '/bucket/dir/file.gzip'

def deferrableTask(filePath, api_url, post_body):
  with gcs.open(filePath, 'w') as f:
      request = urllib2.Request(api_url, post_body)
      try:
        response = urllib2.urlopen(request, timeout = 600)
      except urllib2.HTTPError, e:
        raise customError(e)
      else:
        while True:
          chunk = response.read(16 * 1024)
          if not chunk: break
          f.write(chunk)
      f.close()
      del f
  gc.collect()

上面的任务是使用任务队列来推迟的。一个队列中最多可以有 40 个同时运行。在我的app.yaml 中,我有以下设置:

    instance_class: F4_1G
    automatic_scaling:
      max_concurrent_requests: 4

此代码用于将 api 数据写入云存储。当我开始执行数百个这样的请求时,我开始遇到内存问题。

请求的 gzip 文件大小从 300 kb 到 10-20 Mb 不等,我认为通过使用 gc.collect() 并结合限制并发实例请求的数量,足以减少内存泄漏。我也知道 urllib2 只是应用程序引擎的 urlfetch 的包装器,但提取不是问题,而是缩放。

变量f 占用多少内存?是否可以直接流式传输到 Google Cloud Storage,而不是先将数据加载到实例内存?

【问题讨论】:

我也有同样的问题。我们的网络应用程序正在尝试将write 一个文件发送到 GCS,该文件只有 20 MB,并且请求经常失败并出现错误:Exceeded soft private memory limit of 128 MB with 216 MB after servicing 0 requests total 我没有使用任何缩放。我也没有使用 F4_1G 机器,我使用的是默认的 F1s。我认为这个问题与实例类或缩放设置无关。在仅尝试 1 个请求后,我在单个 F1 实例上遇到内存错误。 cloudstorage 库一定有问题? 我认为是这样。即使使用强制垃圾回收,实例也会将过多的任务保留在内存中,这让我相信 App Engine 本身存在问题。唯一的解决方法是将失败的任务发送到重复队列以稍后重试,但即便如此,一些更大的任务仍然无法完成。 感谢@Jabberwockey 的更新。在您的情况下,您已经使用了可用的最佳实例类,因此您无法再增加内存。我们只使用 F1s,所以我将项目更改为使用 F4s (512MB)。它已经稳定运行了一天,没有任何错误。内存偶尔会激增,但最终会再次下降。 我也有同样的问题。我不得不将服务器密钥部署到数十个媒体服务器,以便将声音文件直接上传到 gcs。直接上传减少了内存错误。但在某些情况下,我不能使用直接上传方法。我找不到任何解决此泄漏的方法。 【参考方案1】:

有一种方法,您可以直接从外部应用程序将数据写入 GCS,为此您必须将存储桶的 ACL 更改为公共,然后在云存储 API 的帮助下将数据写入存储桶.

另外,请告诉我您是否错过了问题中有关自动扩展配置的任何详细信息。如果是,请说明这些细节。

【讨论】:

数据是机密和专有的,这意味着存储桶永远不能公开。

以上是关于写入云存储时 GAE 内存泄漏,我可以流式传输吗?的主要内容,如果未能解决你的问题,请参考以下文章

通过压缩将HTTP发布多部分/表单数据流式传输并上传到存储中?

通过 Azure 媒体服务从 Azure 云存储 Blob 流式传输 mp3(仅限音频)

在 java servlet 中流式传输大文件

从 Google 云存储中移动/流式传输数据

在 try-with-resources 块之外流式传输 JOOQ 结果时,我是不是会冒 JDBC 连接泄漏的风险?

使用 GSON 的 JsonReader 流式传输 Json 文件时,您可以将对象转储为字符串吗?