Skip to content

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

Description

@Bewear777

问题描述

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 代码块中释放,无需再次释放。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions