vesoft-inc / vesoft-inc/nebula-java

【3.8】ScanEdgeResultIterator.next() 因重复释放 Storage 连接而阻塞

Open Beginner friendly
#654 0 comments 0 reactions 0 assignees View on GitHub

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

复现场景

  1. 集群中存在三个 Storage 地址。
  2. 指定扫描单个 partition,此时只有一个 PartScanInfo
  3. 调用 ScanEdgeResultIterator.next()
  4. 两个没有匹配 partition 的 worker 执行 countDown() 后返回。
  5. 扫描 leader partition 的 worker 在 finally 中第一次释放连接。
  6. 随后,该 worker 在执行 countDown() 前再次调用 pool.release(...)
  7. 最终 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

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.