gpt4 book ai didi

http - 从远程服务器提交 neo4j 批处理时出现 IncompleteRead 错误;格式错误的 HTTP 响应

转载 作者:可可西里 更新时间:2023-11-01 15:23:48 26 4
gpt4 key购买 nike

我已经在服务器 A 上设置了 neo4j,并且我在服务器 B 上运行了一个应用程序来连接到它。

如果我在服务器 A 上克隆应用程序并运行单元测试,它工作正常。但是在服务器 B 上运行它们,设置运行了 30 秒并失败并显示 IncompleteRead:

Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/nose-1.3.1-py2.7.egg/nose/suite.py", line 208, in run
self.setUp()
File "/usr/local/lib/python2.7/site-packages/nose-1.3.1-py2.7.egg/nose/suite.py", line 291, in setUp
self.setupContext(ancestor)
File "/usr/local/lib/python2.7/site-packages/nose-1.3.1-py2.7.egg/nose/suite.py", line 314, in setupContext
try_run(context, names)
File "/usr/local/lib/python2.7/site-packages/nose-1.3.1-py2.7.egg/nose/util.py", line 469, in try_run
return func()
File "/comps/comps/webapp/tests/__init__.py", line 19, in setup
create_graph.import_films(films)
File "/comps/comps/create_graph.py", line 49, in import_films
batch.submit()
File "/usr/local/lib/python2.7/site-packages/py2neo-1.6.3-py2.7-linux-x86_64.egg/py2neo/neo4j.py", line 2643, in submit
return [BatchResponse(rs).hydrated for rs in responses.json]
File "/usr/local/lib/python2.7/site-packages/py2neo-1.6.3-py2.7-linux-x86_64.egg/py2neo/packages/httpstream/http.py", line 563, in json
return json.loads(self.read().decode(self.encoding))
File "/usr/local/lib/python2.7/site-packages/py2neo-1.6.3-py2.7-linux-x86_64.egg/py2neo/packages/httpstream/http.py", line 634, in read
data = self._response.read()
File "/usr/local/lib/python2.7/httplib.py", line 532, in read
return self._read_chunked(amt)
File "/usr/local/lib/python2.7/httplib.py", line 575, in _read_chunked
raise IncompleteRead(''.join(value))
IncompleteRead: IncompleteRead(131072 bytes read)
-------------------- >> begin captured logging << --------------------
py2neo.neo4j.batch: INFO: Executing batch with 2 requests
py2neo.neo4j.batch: INFO: Executing batch with 1800 requests
--------------------- >> end captured logging << ---------------------

当我提交足够大的批次时会发生异常。如果我减小数据集的大小,它就会消失。它似乎与请求大小而不是请求数量有关(如果我向正在创建的节点添加属性,我可以减少请求)。

如果我使用 batch.run()而不是 .submit() , 我没有收到错误,但测试失败;似乎这批被默默拒绝了。如果我使用 .stream()并且不要迭代结果,同样的事情发生在 .run() ;如果我对它们进行迭代,我会得到与 .submit() 相同的错误(除了它是“0 字节读取”)。

查看 httplib.py 表明,当 HTTP 响应具有 Transfer-Encoding: Chunked 时,我们将收到此错误。并且不包含预期的块大小。所以我在测试中运行了 tcpdump,事实上,这似乎就是正在发生的事情。最后一个块的长度为 0x8000 ,其最后的字节是
"http://10.210.\r\n
0\r\n
\r\n

(为清晰起见,在\n 之后添加了换行符。)这看起来是正确的分块,但第 0x8000 个字节是第一个“/”,而不是第二个“.”。提前八字节。它也不是一个完整的响应,是无效的 JSON。

有趣的是,在这个块中,我们得到以下数据:
"all_relatio\r\n
1280\r\n
nships":

也就是说,它看起来像是一个新块的开始,但嵌入在旧块中。如果我们注意到它开始,这个新块将在正确的位置(上面的第二个“.”)结束。如果块头不存在,旧块将在正确的位置结束(8 个字节之后)。

然后我提取了批处理的 POST 请求,并使用 cat batch-request.txt | nc $SERVER_A 7474 运行它。 .对此的响应是一个有效的分块 HTTP 响应,包含一个完整的有效 JSON 对象。

我想也许 netcat 发送请求的速度比 py2neo 快,所以我引入了一些减速
cat batch-request.txt | perl -ne 'BEGIN { $| = 1 } for (split //) { select(undef, undef, undef, 0.1) unless int(rand(50)); print }' | nc $SERVER_A 7474

但它继续工作,尽管现在慢得多。

我还尝试在服务器 A 上执行 tcpdump,但对 localhost 的请求不会通过 tcp。

我仍然有一些我没有探索过的途径:我还没有弄清楚请求失败的可靠性或在哪些条件下(我曾经看到它成功的批处理通常会失败,但我还没有探索边界)。而且我还没有尝试直接从 python 发出请求,而不通过 py2neo。但我并不特别期望其中任何一个能够提供非常丰富的信息。除了使用wireshark的'follow TCP stream'提取HTTP session 外,我没有仔细查看TCP转储;我真的不知道我会在那里寻找什么。有很大一部分wireshark在失败的转储中以黑色突出显示,而在成功的转储中只有孤立的黑色线条,这可能是相关的吗?

所以现在:有人知道会发生什么吗?还有什么我应该尝试诊断问题的吗?

TCP 转储在这里: failedsuccessful .

编辑:我开始理解失败的 TCP 转储。整个对话需要大约 30 秒,并且有大约 28 秒的间隔,两个服务器都在发送 ZeroWindow TCP 帧 - 这些是我提到的黑线。

首先py2neo填满neo4j的窗口; neo4j 发送一个框架,说“我的窗口已满”,然后是另一个填满 py2neo 窗口的框架。然后我们花了大约 28 秒的时间,他们每个人都只是说“是的,我的窗口还是满的”。最终,neo4j 再次打开它的窗口,py2neo 发送更多数据,然后 py2neo 打开它的窗口。他们都发送了更多的数据,然后 py2neo 完成了它的请求,neo4j 在也完成之前发送了更多的数据。

所以我在想问题可能是这样的,他们都拒绝处理更多的数据,直到他们发送了更多的数据,并且在另一个处理一些之前都不能发送更多的数据。最终,neo4j 进入“出现问题”循环,py2neo 将其解释为“继续发送更多数据”。

这很有趣,但我不确定这意味着什么,从 neo4j 发送到 py2neo 的倒数第二个 TCP 帧开始 \r\n1280\r\n - 假块的开始。 \r\n8000\r\n开始实际的块,只是在一个不起眼的 TCP 帧中出现。 (这是 py2neo 完成发送其 post 请求后发送的第三帧。)

编辑 2:我检查了一下python卡在哪里。不出所料,是在发送请求时 - 所以 BatchRequestList._execute()直到 neo4j 放弃后才返回,这就是为什么 .run().stream().submit() 做得更好.

最佳答案

似乎解决方法是设置标题 X-Stream: true;format=pretty . (默认情况下它只是 true ;它曾经很漂亮,但由于 this bug 被删除了(看起来它实际上是一个 neo4j 错误,而且似乎仍然是开放的,但目前对我来说不是问题)。

看起来,通过设置 format=pretty ,我们导致 neo4j 在处理整个输入之前不发送任何数据。因此它不会尝试发送数据,发送时不会阻塞,并且在发送某些内容之前不会拒绝读取。

删除 X-Stream完全 header ,或将其设置为 false , 好像和设置 format=pretty 效果一样(例如,让 Neo4j 发送一个响应,该响应是分块的、打印精美的、不包含状态代码的,并且在整个请求处理完毕之前不会发送),这有点奇怪。

您可以为单个批次设置标题

batch._batch._headers['X-Stream'] = 'true;format=pretty'

或者设置全局标题
neo4j._add_header('X-Stream', 'true;format=pretty')

关于http - 从远程服务器提交 neo4j 批处理时出现 IncompleteRead 错误;格式错误的 HTTP 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22530421/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com