【3.8】ScanEdgeResultIterator.next() 因重复释放 Storage 连接而阻塞
評価
調査の方向性
client/src/main/java/com/vesoft/nebula/client/storage/scan/ScanEdgeResultIterator.java から始め、next() と countDownLatch.countDown() 周辺の worker のクリーンアップに注目してください。解放処理を ScanVertexResultIterator および既存の finally ブロックと比較してください。各借用済み Storage 接続が一度だけ解放され、説明されている単一パーティションのスキャンで ScanEdgeResultIterator.next() がブロックせずに戻ることが完了の条件です。
索引モデルが issue の本文から書いたものです。
説明
问题描述
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 代码块中释放,无需再次释放。
- 主要言語
- Java
- スター
- 196
- フォーク
- 127
- 平均マージ
- 10時間 56分
- マージ済み PR(30日)
- 2
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
vesoft-inc/nebula-java のほかの issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 20/100
vesoft-inc/nebula-java#665 ·
-
【5.2.1】在获取连接时偶发报错再び着手できるかも @Nicole00 が 215 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンaffects/none severity/none type/bug
vesoft-inc/nebula-java#644 · 担当者 1 名 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 35/100
vesoft-inc/nebula-java#629 · コメント 1 件 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 48/100
vesoft-inc/nebula-java#621 ·
-
難易度 3/5 1〜2日 初心者へのやさしさ 45/100
vesoft-inc/nebula-java#620 · コメント 2 件 · リアクション 1 件 ·
vesoft-inc/nebula-java の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 75/100
521xueweihan/HelloGitHub#4105 ·
-
Awaiting further input from submitter
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
Regression in 5.9.0: CuratorCache fails with ClassCastException when the client is not a CuratorFrameworkBase対応中かも @sftwnd が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
メンテナーはふだん 1 日以内に返信