我有一个处理特定二进制协议的TCP服务器。某些请求包含要写入文件的大量数据。服务器使用NIO框架(netty),并在其中具有逻辑来处理已分解为多个帧的消息。
当单个帧进入时,如果要将该帧中的数据写入文件,则打开该文件并写入数据。即使流尚未完成,我希望另一个带有数据的帧被附加到同一个文件,我当前关闭该文件,直到我收到下一帧,此时我重新打开它并附加其他数据。
我选择了这种方法,因为它似乎是最安全的方法,避免留下打开的文件句柄,并通过一些错误而不关闭它们,但是,我担心这会产生负面的性能影响。将文件句柄保持打开是否更好(或在这种情况下是最佳实践)(因此保持对打开的FileOuputStream或Channel的引用)?打开文件句柄的数量是否存在资源限制问题?
答案 0 :(得分:3)
建立TCP连接握手等需要10到100毫秒,所以理想情况下你不会经常非常。看看你的解释,我肯定会保持连接打开,因为如果你不断创建新的连接,你的有效带宽真的有限。
请记住,无论如何,连接将在关闭时关闭,并且如果对象离开已定义的范围,将在gc时关闭。看看你是否不能将连接放在范围内以利用它。
<强>更新强>
刚刚看到你的意思是磁盘的评论。但是,同样的论点也适用,但是因为打开一个文件应该花费的时间通常只有几毫秒 - 但可能仍然只有10毫秒。
答案 1 :(得分:3)
恕我直言,我认为最好让文件句柄保持打开状态。
多年来我straced
无法通过套接字传输文件,我从未见过一个反复关闭并打开目标文件的程序。
此外,我可能会将传入的流写入临时文件名,并且只在完成时将其重命名为正确的文件名。
答案 2 :(得分:1)
看守答案:
像
这样的东西 /* 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);
当然,只有文件打开/关闭实际上是在浪费时间才有意义。
如果您可以对现有系统进行负载测试,并尝试分析两者所需的时间 当然,您可以更好地处理您的具体需求。