在googleappengine(python)上从Google云存储读取文件时内存泄漏

2024-04-28 20:29:47 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是在googleappengine上运行的python代码的一部分。 它使用cloudstorage客户端从Google云存储获取一个文件。在

问题是每次代码读取一个大文件(大约10米),实例中使用的内存将线性增加。很快,由于“超过了128 MB的软专用内存限制,在总共处理了40个请求后,该进程被终止。”。在

class ReadGSFile(webapp2.RequestHandler):
    def get(self):
        import cloudstorage as gcs

        self.response.headers['Content-Type'] = "file type"
        read_path = "path/to/file"

        with gcs.open(read_path, 'r') as fp:
            buf = fp.read(1000000)
            while buf:
                self.response.out.write(buf)
                buf = fp.read(1000000)
            fp.close()

如果我注释掉下面的一行,那么实例中的内存使用量确实会改变。所以这应该是webapp2的问题。在

^{pr2}$

假设webapp2在完成响应后将释放内存空间。但在我的代码中,它没有。在


Tags: 文件path实例内存代码selfreadresponse
3条回答

我也经历过类似的问题。在我的代码中,我按顺序下载了相当多的1-10MB文件,对所有文件进行一些处理,然后将结果发布到云端。在

我亲眼目睹了严重的内存泄漏无法连续处理超过50-100次的下载。在

由于不愿意将下载代码重写到Blobstore,我尝试了一个最后的实验,每次下载后手动调用垃圾回收:

import gc
gc.collect()

我现在运行代码几分钟,没有任何“超过软私有内存限制”,并且实例的内存占用似乎以慢得多的速度增长。在

显然,这可能只是一个好运气,占用空间仍在逐渐增加,但有一些下降,并且实例已经服务了2000个请求。在

根据以上用户voscausa的评论,我改变了文件下载的方案,即使用Blobstore来服务文件下载。现在解决了内存泄漏问题。在

参考号:https://cloud.google.com/appengine/docs/python/blobstore/#Python_Using_the_Blobstore_API_with_Google_Cloud_Storage

from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers

class GCSServingHandler(blobstore_handlers.BlobstoreDownloadHandler):
  def get(self):
    read_path = "/path/to/gcs file/"  # The leading chars should not be "/gs/"
    blob_key  = blobstore.create_gs_key("/gs/" + read_path)

    f_name = "file name"
    f_type = "file type" # Such as 'text/plain'

    self.response.headers['Content-Type'] = f_type
    self.response.headers['Content-Disposition'] = "attachment; filename=\"%s\";"%f_name
    self.response.headers['Content-Disposition'] += " filename*=utf-8''" + urllib2.quote(f_name.encode("utf8"))

    self.send_blob(blob_key)

尝试清除上下文缓存中的内容。在

from google.appengine.ext import ndb

context = ndb.get_context()
context.clear_cache()

See documentation here

With executing long-running queries in background tasks, it's possible for the in-context cache to consume large amounts of memory. This is because the cache keeps a copy of every entity that is retrieved or stored in the current context. To avoid memory exceptions in long-running tasks, you can disable the cache or set a policy that excludes whichever entities are consuming the most memory.

您也可以尝试清除webapp2响应对象缓冲区。在循环之前插入这行代码

^{pr2}$

The response buffers all output in memory, then sends the final output when the handler exits. webapp2 does not support streaming data to the client. The clear() method erases the contents of the output buffer, leaving it empty.

Check this link

相关问题 更多 >