[BUG] - Java-Chassis 新版本无法自动清理临时上传文件的句柄
まだ誰も着手していません。
評価
調査の方向性
foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/FileUploadPart.java から始め、issue #4476 に関連する変更を確認してください。Linux 上で Java-Chassis 2.8.24 を使用してハンドル保持の動作を再現し、その後、非同期アップロード処理を壊すことなく Java 8 と Java 21 との互換性を維持できるクリーンアップ設計を決定して検証してください。
索引モデルが issue の本文から書いたものです。
説明
Steps to Reproduce
- 编写一个处理文件上传请求的controller.
- 接收到上传文件参数后, 打开文件流, 不关闭, 直接返回.
- 在Java-Chassis 1.x分支上可以观察到一段时间后文件句柄会被清理, 而在 Java-Chassis 2.8.24 版本, 文件句柄会一直存在, 直到进程重启才会消失.
注意:
- 实际测试发现此问题在Windows上不会出现(Java8), 我们是在Linux上复现的问题.
- 打开文件流不关闭只是为了让问题必现. 实际上即使业务代码有正常的close调用也可能遇到类似的问题, 因为业务处理文件流的逻辑可能超时, 导致 Vert.x 执行临时文件清理回调时文件流仍然处于打开的状态.
Expected Behavior
预期 Java-Chassis 2.8.24 能像 Java-Chassis 1.x 分支一样, 能够自动兜底清理文件句柄.
Servicecomb Version
2.8.24
Additional Context
根因分析
导致 Java-Chassis 1.x 和 2.8.x 差异的代码在于:
在更早的版本中, 它返回的是一个 FileInputStream:
而 2.8.20 版本对此做了上述修改, 实测返回的是 sun.nio.ch.ChannelInputStream 类型的流.
在 Java8 中, FileInputStream 的 finalize 方法会执行 close 方法, 而 sun.nio.ch.ChannelInputStream 的 finalize 方法是空的. 这就导致 Java-Chassis 2.8.19 及之前的版本, 即使业务代码由于各种各样的原因没有执行 close 方法, FileInputStream 也能在被GC回收时兜底关闭文件句柄, 而在升级到 Java-Chassis 2.8.20 之后就只能泄漏句柄了.
回溯 Java-Chassis 的代码修改记录可知, 这个变化是为了修复另外一个问题而引入的:
https://github.com/apache/servicecomb-java-chassis/issues/4476
解决思路
Java-Chassis 已经不适合将文件输入流的类型改回 FileInputStream 了.
除了上面说的 issue #4476 的原因, 高版本的 Java 还废弃了 finalize 方法, 即使用回 FileInputStream 也不能兜底关闭文件句柄.
为了能够同时兼容 Java8 和 Java21, 也不适合选用 Cleaner 机制(Java9才具备此特性).
目前能想到的解决办法:
-
基于 Java-Chassis 自身的 Invocation 生命周期管理机制来做自动清理动作.
此方案的风险在于, 考虑到业务可能在 controller 层获取上传文件参数后, 异步调度到其他任务线程池处理, 因此在 Invocation 的结束事件发生时就直接关闭流的话可能会导致业务视角看到的Java-Chassis框架行为发生了影响业务功能的不兼容变化.
-
记录已打开的 InputStream, 在后台定时任务中监控其关闭状态.
此方案可以一定程度规避方案1的风险, 但存在内存用量上升甚至泄漏的风险, 若选择这个思路, 也需要小心进行可靠性设计.
此外, 建议Java-Chassis增加对 FileUploadPart 的打开流的调用记录的监控, 便于辅助业务分析此类文件句柄泄漏问题的触发代码位置.
- 主要言語
- Java
- スター
- 1.9k
- フォーク
- 813
- 平均マージ
- 8日 23時間
- マージ済み PR(30日)
- 1
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
apache/servicecomb-java-chassis のほかの issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
apache/servicecomb-java-chassis#5106 ·
-
question
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
apache/servicecomb-java-chassis#5153 · コメント 1 件 ·
-
question
難易度 4/5 3〜5日 初心者へのやさしさ 25/100
apache/servicecomb-java-chassis#5146 ·
-
[FEATURE] - When will ServiceComb support Spring Boot 4.x, Spring Framework 7.x, and Jackson 3.x? オープンenhancement
難易度 5/5 1週間以上 初心者へのやさしさ 25/100
apache/servicecomb-java-chassis#5145 ·
-
2.x bug
apache/servicecomb-java-chassis#5141 · 担当者 1 名 ·
apache/servicecomb-java-chassis の issue をすべて見る
似ている issue
-
area/plugin
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
kestra-io/plugin-kestra#190 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
google-ai-edge/LiteRT-LM#3739 ·
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
integra-team-red/meet-map#249 ·
-
[Studio][Bug] Cancelled create-user dialog keeps the password and admin switch for the next attempt オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
apache/rocketmq-dashboard#5064 ·