在App Engine(Python)中释放URL获取后的内存的最佳实践

3 投票
2 回答
766 浏览
提问于 2025-04-17 14:02

我的问题是,如何在应用引擎上最好地释放异步URL获取的响应所需的内存。基本上,我在Python中做的事情是:

rpcs = []

for event in event_list:
    url = 'http://someurl.com'
    rpc = urlfetch.create_rpc()
    rpc.callback = create_callback(rpc)
    urlfetch.make_fetch_call(rpc, url)
    rpcs.append(rpc)

for rpc in rpcs:
    rpc.wait()

在我的测试场景中,这样处理1500个请求没问题。但我需要一种架构,能够在短时间内处理更多的请求。

然后有一个回调函数,它会将任务添加到队列中,以处理结果:

def event_callback(rpc):
    result = rpc.get_result()
    data = json.loads(result.content)
    taskqueue.add(queue_name='name', url='url', params={'data': data})

我的问题是,我同时发起了太多的RPC调用,导致我的实例内存崩溃:“在处理975个请求后,超过了159.234 MB的软私有内存限制”

我已经尝试了三种方法:

del result
del data

还有

result = None
data = None

我在回调函数后手动运行了垃圾回收器。

gc.collect()

但是似乎没有任何方法能在回调函数添加任务到队列后立即释放内存,因此实例崩溃了。还有其他办法吗?

2 个回答

1

使用任务队列来处理urlfetch,这样可以分散任务,避免内存耗尽。你可以注册命名的任务,并把事件列表的游标传递给下一个任务。在这种情况下,你可能想要同时获取和处理数据,而不是每处理一次就注册一个新任务,特别是当处理的内容还包括对数据存储的写入时。

我发现ndb可以让这些异步解决方案变得更优雅。

可以看看Brett Slatkin关于可扩展应用的演讲,或者看看这个关于管道的讲座。

2

错误的方法是:把这些网址放进一个队列里,增加处理的速度到你想要的值(默认是每秒5个)。然后让每个任务去处理一个网址的获取(或者一组网址)。请注意,有一个安全限制是每分钟最多只能进行3000次网址获取的API调用(而且一次网址获取可能会使用多个API调用)。

撰写回答