您的JVM是否泄漏文件描述符-像我的一样?

前言:此处描述的两个问题是在一年前发现并修复的。 本文仅用作历史证明,也是有关解决Java中文件描述符泄漏的初学者指南。

Ultra ESB中,我们使用内存RAM磁盘文件缓存来进行快速且无垃圾的有效负载处理。 一段时间以前,我们在共享的SaaS AS2网关上遇到了一个问题,该缓存随着时间的推移泄漏了文件描述符。 最终,在击中系统ulimit时,导致too many open files错误too many open files

有弹性的城堡军团:流支持的MIME部分中的剩余部分?

我们发现其中一个罪魁祸首是Bouncy Castle ,这是著名的安全提供程序,自Ultra ESB Legacy以来,我们一直深爱着它。

通过一些简单的工具,我们发现BC习惯了对MIME部分调用getContent()以确定它们的类型(例如, instanceof检查)。 没错,这本身并不是犯罪。 但是我们的大多数MIME部分都是文件支持的 ,另一端带有文件缓存文件-这意味着每个getContent()都会为该文件打开一个新流。 因此,现在有指向我们的文件缓存的杂散流(以及文件描述符)。

这些已经足够了,我们将用尽分配给Ultra ESB(Java)进程的文件描述符配额。

让他们变得懒惰!

我们不想弄乱BC代码库。 因此,我们找到了一个简单的解决方案:使用“惰性”流创建所有文件支持的MIME部分。 我们(以前)同事Rajind写了LazyFileInputStream -灵感LazyInputStreamjboss-vfs -打开只有当实际文件read尝试。

BC很高兴,文件缓存也很高兴。 但是我们是最快乐的

Hibernate JPA:晚饭后清理,也就是关闭消耗的流

我们发现的另一个错误是某些数据库操作留下了未关闭的文件句柄。 显然,只有当我们将流支持的Blob馈送到Hibernate时,流才通常来自文件缓存项。

经过一番挖掘之后,我们提出了一个理论,即Hibernate不会关闭这些Blob条目的基础流。 (这是有道理的,因为java.sql.Blob接口没有公开Hibernate可以用来操作基础数据源的任何方法。)但是,这是一个问题,因为丢弃的流(以及关联的文件句柄)不会得到发布直到下一个GC。

对于一个短期应用程序来说,这本来可以,但是像我们这样长期运行的应用程序很容易用完文件描述符。 例如突然而持续的峰值。

让他们自动关闭!

我们不想失去流媒体的好处,但是我们也无法控制流媒体。 您可能会说我们应该将流放在可自动关闭的结构中(例如try-with-resources )。 不错的尝试; 但是可悲的是,Hibernate在我们的执行范围之外(特别是在@Transactional流中)读取它们。 一旦我们开始在代码范围内关闭流,我们的数据库操作就开始惨败-尖叫“流已关闭!”。

他们说, 在罗马时,就像罗马人一样

因此,我们决定不打扰Hibernate,而是决定自己处理流。

Rajind(是的,还是他)再次入侵了SelfClosingInputStream包装器 。 这将跟踪从底层流读取的数据量,并在读取最后一个字节后立即将其关闭。

(我们确实考虑过使用现有选项,例如来自Apache commons-io AutoCloseInputStream ;但是发生了,我们到处都需要一些自定义设置,例如详细的跟踪日志记录。)

底线

当涉及到Java中的资源管理时,很容易过度关注内存和CPU(处理),而忽略其余部分。 但是虚拟资源(例如临时端口每个进程的文件描述符 )可能同样重要,甚至更多。

尤其是在长时间运行的流程(例如我们的AS2 Gateway SaaS应用程序)上,它们实际上可以成为沉默的杀手。

您可以通过两种主要方式检测这种“泄漏”:

  • “单周期”资源分析 :运行一个完整的处理周期,比较前后的资源使用情况
  • 长期监控 :持续记录和分析资源指标以识别趋势和异常

在任何情况下,修复泄漏都不是一件容易的事。 一旦您清楚地了解要处理的内容。

祝您好运,寻找您的资源消耗d(a)守护程序!

翻译自: https://www.javacodegeeks.com/2019/10/is-your-jvm-leaking-file-descriptors-like-mine.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值