py2neo使用Bolt

时间:2017-01-12 20:06:49

标签: neo4j py2neo

最近,一个使用py2neo包并通过Bolt协议连接的脚本开始意外地与ProtocolError: Server closed connection失败,我很难理解为什么。请注意,使用HTTP作为协议时脚本可以正常工作。

该脚本提取Neo4j图,在Python中对其进行扩充,然后尝试将相关更改推送回数据库。整个过程大约需要一个小时,并且可靠地工作了很长一段时间,但最近推动阶段开始失败。

如果我创建一个玩具示例,绕过拉动和扩充,那么推动工作,因此我认为服务器因超时而关闭了连接,但是我找不到py2neo中Bolt的任何超时相关参数。注意我已将HTTP套接字超时设置为9999秒(~2.75小时),

from py2neo.packages.httpstream import http
http.socket_timeout = 9999

虽然我对此的理解是i)它与Bolt无关,ii)超时处于连接级别,这大大超过了脚本运行的时间。

作为参考,我使用的是Neo4j v3.0.3和py2neo v3.1.2。堆栈跟踪是:

File "/usr/local/lib/python2.7/dist-packages/py2neo/database/__init__.py", line 1017, in __exit__
self.commit()
File "/usr/local/lib/python2.7/dist-packages/py2neo/database/__init__.py", line 1059, in commit
self._post(commit=True)
File "/usr/local/lib/python2.7/dist-packages/py2neo/database/__init__.py", line 1291, in _post
self.finish()
File "/usr/local/lib/python2.7/dist-packages/py2neo/database/__init__.py", line 1296, in finish
self._sync()
File "/usr/local/lib/python2.7/dist-packages/py2neo/database/__init__.py", line 1286, in _sync
connection.fetch()
File "/usr/local/lib/python2.7/dist-packages/py2neo/packages/neo4j/v1/bolt.py", line 323, in fetch
raw.writelines(self.channel.chunk_reader())
File "/usr/local/lib/python2.7/dist-packages/py2neo/packages/neo4j/v1/bolt.py", line 174, in chunk_reader
chunk_header = self._recv(2)
File "/usr/local/lib/python2.7/dist-packages/py2neo/packages/neo4j/v1/bolt.py", line 157, in _recv
raise ProtocolError("Server closed connection")
ProtocolError: Server closed connection

,剥离的Python代码的形式为

import py2neo
from py2neo.packages.httpstream import http
http.socket_timeout = 3600

graph = py2neo.Graph(
    host='localhost',
    bolt=True,
    bolt_port=4096,
    http_port=4095,
)

# Pull the graph from the Neo4j database via graph.run(...) statements,
# augments the graph etc.
# ...

# Exception is thrown when the following push transaction is executed.
with graph.begin() as tx:
    statement = """
        UNWIND {rows} AS row
        WITH row.source AS source, row.target AS target
        MATCH (s:Entity)
        USING INDEX s:Entity(uuid)
        WHERE s.uuid = source
        MATCH (t:Entity)
        USING INDEX t:Entity(uuid)
        WHERE t.uuid = target
        MATCH (s)-[r:FAVORITED]->(t)
        DELETE r
    """

    rows = [{
        'source': '8267d7d0-a837-11e6-b841-22000bcec6a9',
        'target': 'c6296c97-a837-11e6-b841-22000bcec6a9',
    }]

    tx.run(statement, rows=rows)

有没有人对如何进一步调试此内容或导致连接关闭的原因有任何建议?我查看了_recv函数,但是为什么插槽没有收到数据也不明显。

查看Neo4j debug.log文件唯一可能的相关错误是

java.io.IOException: Connection reset by peer
at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.netty.buffer.PooledUnsafeDirectByteBuf.setBytes(PooledUnsafeDirectByteBuf.java:311)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:881)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:242)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:119)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:111)
at java.lang.Thread.run(Thread.java:745)

我还检查了服务的正常运行时间,并确认它在整个脚本持续时间内运行(HH:MM:SS),

 > ps -p "14765" -o etime=
 16:55:31

1 个答案:

答案 0 :(得分:0)

我认为问题在于:

tx.run(statement, rows=rows)

CypherResoure.run()的第二个参数是参数字典。你作为额外的python参数传递它们。请参阅py2neo code

尝试:

tx.run(statement, {"rows": rows});