如何调试asyncio(使用aiohttp)应用程序以查找内存泄漏?
应用程序:100个异步协程,它们从Redis读取消息,进行一些外部API http调用,并将结果保存到db中。
问题出在这里:在更大的消息数(10k-20k)上,每条消息之后,应用程序使用的RAM内存就在增加。
使用objgraph进行调试,例如:
print(objgraph.show_growth(limit=100))
每条新消息后显示的结果完全相同:
weakref 6163 +4
dict 19192 +3
builtin_function_or_method 1911 +3
tuple 16880 +2
function 25375 +1
method 496 +1
Event 8 +1
Condition 8 +1
deque 14 +1
SplitResult 15 +1
Context 15 +1
Thread 7 +1
这不是我亲手创造的,所以这就是所有第三方依赖项。
还发现了有趣的物品:
词典之一(来自show_growth
)是:
{'_context': <ssl.SSLContext object at 0x10a4ce228>,
'_server_side': False,
'_server_hostname':
'my.host.name',
'_state': 'SHUTDOWN',
'_incoming': <_ssl.MemoryBIO object at 0x10a620b30>,
'_outgoing': <_ssl.MemoryBIO object at 0x10a620b10>,
'_sslobj': <ssl.SSLObject object at 0x10a664ac8>,
'_need_ssldata': True,
'_handshake_cb': <bound method SSLProtocol._on_handshake_complete of <asyncio.sslproto.SSLProtocol object at 0x10a664630>>,
'_shutdown_cb': <bound method SSLProtocol._finalize of <asyncio.sslproto.SSLProtocol object at 0x10a664630>>
}
如您所见,这就像是呼叫或响应的结果。是否有可能所有响应都在这里,所以它可以保存每个响应并且RAM正在增加?
如何处理? 还是可以建议另一种方法来找到弱小的应用程序?
答案 0 :(得分:1)
不断发展的字典是__dict__
异步内部类中的_SSLPipe
。
您会尝试uvloop吗?Шt是具有不同SSL传输实现的替代事件循环。
此外,该错误可能取决于所使用的Python版本。您是否检查了最新的Python(目前为3.8)?