vesoft-inc / vesoft-inc/nebula-java
【3.8】ScanEdgeResultIterator.next() 因重复释放 Storage 连接而阻塞
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 199
- Forks
- 125
- Avg merge
- 5h 6m
- Merged PRs (30d)
- 3
Description
问题描述
nebula-java 3.8 的 ScanEdgeResultIterator.next() 在正常处理响应时,会对同一个 GraphStorageConnection 执行两次 release,导致 next() 一直阻塞、无法返回。
该问题只存在于边扫描方法 ScanEdgeResultIterator 中。点扫描方法 ScanVertexResultIterator 已正确删除重复的 release,没有这个问题。
问题原因
https://github.com/vesoft-inc/nebula-java/pull/605/files#diff-8d4ffb6a9c44959ad0d34a65442ed50ea0d58bce4343ce7b04f815fddfc0e336
PR #605 为连接释放增加了 finally 逻辑:
} finally {
pool.release(leader, connection);
}
但是,ScanEdgeResultIterator 在 worker 末尾仍然保留了原来的连接释放代码:
pool.release(new HostAddress(addr.getHost(), addr.getPort()), connection);
countDownLatch.countDown();
因此,同一个 Storage 连接会被归还连接池两次。
StorageConnPool.release() 最终调用:
GenericKeyedObjectPool.returnObject()
第二次 release 位于 countDownLatch.countDown() 之前。当第二次释放连接无法正常完成时,当前 worker 不会执行 countDown(),外层线程会一直阻塞在:
countDownLatch.await();
在 PR #605 中,ScanVertexResultIterator 原有的第二次 release 已经被删除,因此点扫描不存在这个问题;只有 ScanEdgeResultIterator 遗漏了相同的修改。
影响版本
release-3.8- 提交 Issue 时,
master分支中也存在相同的重复释放代码。
涉及文件:
client/src/main/java/com/vesoft/nebula/client/storage/scan/ScanEdgeResultIterator.java
复现场景
- 集群中存在三个 Storage 地址。
- 指定扫描单个 partition,此时只有一个
PartScanInfo。 - 调用
ScanEdgeResultIterator.next()。 - 两个没有匹配 partition 的 worker 执行
countDown()后返回。 - 扫描 leader partition 的 worker 在
finally中第一次释放连接。 - 随后,该 worker 在执行
countDown()前再次调用pool.release(...)。 - 最终
CountDownLatch的计数停留在 1,next()永远无法返回。
通过 Arthas 可以看到调用线程一直阻塞在:
ScanEdgeResultIterator.next()
-> CountDownLatch.await()
预期行为
每个从连接池借出的 Storage 连接只应释放一次,ScanEdgeResultIterator.next() 应当正常返回。
实际行为
同一个连接被释放两次,导致 worker 没有执行 countDown(),最终使 next() 一直阻塞。
已验证的解决方法
删除 worker 末尾重复的 release 后,问题消失:
- pool.release(new HostAddress(addr.getHost(), addr.getPort()), connection);
countDownLatch.countDown();
该连接已经在现有的 finally 代码块中释放,无需再次释放。
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in client/src/main/java/com/vesoft/nebula/client/storage/scan/ScanEdgeResultIterator.java, focusing on next() and the worker cleanup around countDownLatch.countDown(). Compare its release handling with ScanVertexResultIterator and the existing finally block. Done means each borrowed Storage connection is released once and ScanEdgeResultIterator.next() returns without blocking in the described single-partition scan.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 92/100