保持文件句柄打开,还是根据需要重新打开?

时间:2011-12-20 22:59:54

标签: java

我有一个处理特定二进制协议的TCP服务器。某些请求包含要写入文件的大量数据。服务器使用NIO框架(netty),并在其中具有逻辑来处理已分解为多个帧的消息。

当单个帧进入时,如果要将该帧中的数据写入文件,则打开该文件并写入数据。即使流尚未完成,我希望另一个带有数据的帧被附加到同一个文件,我当前关闭该文件,直到我收到下一帧,此时我重新打开它并附加其他数据。

我选择了这种方法,因为它似乎是最安全的方法,避免留下打开的文件句柄,并通过一些错误而不关闭它们,但是,我担心这会产生负面的性能影响。将文件句柄保持打开是否更好(或在这种情况下是最佳实践)(因此保持对打开的FileOuputStream或Channel的引用)?打开文件句柄的数量是否存在资源限制问题?

3 个答案:

答案 0 :(得分:3)

建立TCP连接握手等需要10到100毫秒,所以理想情况下你不会经常非常。看看你的解释,我肯定会保持连接打开,因为如果你不断创建新的连接,你的有效带宽真的有限。

请记住,无论如何,连接将在关闭时关闭,并且如果对象离开已定义的范围,将在gc时关闭。看看你是否不能将连接放在范围内以利用它。

<强>更新

刚刚看到你的意思是磁盘的评论。但是,同样的论点也适用,但是因为打开一个文件应该花费的时间通常只有几毫秒 - 但可能仍然只有10毫秒。

答案 1 :(得分:3)

恕我直言,我认为最好让文件句柄保持打开状态。

多年来我straced无法通过套接字传输文件,我从未见过一个反复关闭并打开目标文件的程序。

此外,我可能会将传入的流写入临时文件名,并且只在完成时将其重命名为正确的文件名。

答案 2 :(得分:1)

看守答案:

  • 创建处理的工厂类:
    • 如果给定文件仍处于打开状态,则从池中返回打开的文件句柄;
    • 关闭最旧的(最近最少使用的)文件句柄(如果没有) (某些可调上限对您的系统来说似乎是合理的)
    • 在相对较长的持续时间(30秒?分钟?)内关闭计时器以关闭文件句柄 已经有一段时间没用了

这样的东西
    /* initialize once */
    FilePool.setLimit (maxFiles);

    /* called often */
    FilePool.getFile(ident);
    FilePool.closeFile(handle);

    /* protected/internal/… */
    boolean FilePool.reachedLimit ();
    FilePool.closeLeastRecentlyUsed (number);
    OnTimer → FilePool.closeIdleFiles (duration);

当然,只有文件打开/关闭实际上是在浪费时间才有意义。

如果您可以对现有系统进行负载测试,并尝试分析两者所需的时间 当然,您可以更好地处理您的具体需求。