py2neo.Graph的连接池生命周期:当实例不再被程序员引用时,连接会被释放吗?

connection pool life cycle of py2neo.Graph: would the connections be released when the instance is no longer referenced by programmer?

最近我在我的代码中发现了一个可能的 http 连接泄漏问题。我在日志中收到 "Connection pool is full, discarding connection" 消息,但我的代码中并发请求很少。

实际上我是在每次进入API函数时创建一个py2neo.Graph实例,当它离开函数时我没有做关闭行为。

因为py2neo.Graph实例没有close()方法,而且官方文档中也没有关于py2neo.Graph实例生命周期的说法,所以之前一直以为实例会dead 并在程序员代码不再引用时自动释放其资源(如池中的 http 连接)(因为 python 将在一个对象的引用计数为零时执行删除)。

那么实例的引用被释放时的实际行为是什么?管理 py2neo.Graph 实例的正确方式是什么?

Because there is no close() method for py2neo.Graph instance and there is no statement about the life cycle of py2neo.Graph instance in official documentation so I used to think that the instance would dead and automatically release its resources (like http connections in the pool) when it is no longer referenced by programmer's code (for python will execute deletion when the reference count of one object reaches zero).

当变量不再被引用时,Python 执行删除是对的,但这不是你应该依赖的东西,因为不能保证它会被实际调用。

对于网络连接,您想显式关闭它们,通常使用上下文管理器或调用 close() 方法。 urllib3 提供了执行此操作的方法,但它们必须在 py2neo 级别使用。

所以 Database 对象包含类型 HTTPConnectorConnector 如果您指定了 HTTP URL,并且您可以通过 connector 属性 然后 close() 它。如果您有 Graph,您可以从中访问 database。所以正确关闭 py2neo 图看起来像这样:

graph = Graph(...)

# use the graph...

graph.database.connector.close()  # close the connection pool

但我不py2neo打算这样使用:它们实际上有一个class级Database cache,所以当你打开多个Graph() 实例(这就是你正在做的),那么同一个数据库将被重用,最终是同一个连接池。

这就是为什么您可以简单地调用 Database.forget_all() class 方法来清空缓存并关闭所有连接的原因。

我不确定这是否适用于您的情况,无论如何,重用现有连接通常会更快,而 urllib3 可以很好地做到这一点,在一种情况下:您需要确保连接被释放到游泳池。如果你不这样做,那么你很快就会达到连接限制,这意味着创建新连接需要丢弃旧连接,这会产生你的 "Connection pool is full, discarding connection" 警告。

但老实说这里看起来 py2neo 没有使用流,所以所有连接都应该立即放回池中,除非你有超过 40 concurrent requests, the current default. Maybe if you share your actual code in the form of a minimal example 帮助会更容易。