【发布时间】:2015-07-02 21:07:23
【问题描述】:
我正在开发一个应用程序,该应用程序以定义的时间间隔轮询目录中的新输入文件。大致流程是:
- 输入文件被另一个应用通过 FTP 传送到着陆带目录
- 我们的应用唤醒
- 列出输入目录中的文件
- 以原子方式将文件移动到单独的暂存目录
- 启动工作线程(通过工作分配队列)以使用暂存目录中的文件
- 回去睡觉
我发现了一个问题,应用程序会在输入文件不完整且仍在传输过程中提取文件,从而导致工作线程错误,需要人工干预。这是我们需要避免的情况。
我应该注意到文件传输会成功完成,服务器会得到一个完整的副本,但这会发生在应用程序因错误放弃后。
我想以一种干净的方式解决这个问题,虽然我有一些解决方案的想法,但他们都有我不喜欢的问题。
这是我考虑过的:
- 强制其他应用程序(其中一些是我们公司外部的)最初将输入文件传输到保存目录,然后在传输后将它们原子地移动到输入目录中。这是我有过的最有力的想法,但我不喜欢这个,因为我不相信它会永远正确实施。
- 重试有限次出错。我不喜欢这个,因为它是一个部分解决方案,它对可能违反的传输时间和文件大小做出了假设。它还会模糊真正坏的文件和刚刚传输不完全的文件之间的界限。
- 观察文件大小,如果文件大小在规定的时间段内没有改变,则只提取文件。我不喜欢这个,因为它在我们的环境中太复杂了:轮询器是一个非并发的集群 Quartz 作业,所以我不能只将这些信息保存在内存中,因为该作业可以在服务器之间反弹。我可以将它存储在 jobdetail 中,但这个解决方案感觉太复杂了。
我不是第一个遇到这个问题的人,所以我相信我会在这里得到更好的想法。
【问题讨论】:
-
我不知道 Java 的文件/目录更新事件的工作方式是否不同,或者那些包含在 Apache Camel 中的文件系统观察程序。但我认为,如果您尝试在复制文件之前以独占方式打开文件并且失败,您应该知道写入过程尚未完成:看看这里stackoverflow.com/questions/128038/…
-
你真的要投票吗?为什么不改用java nio watch service API?
-
@Alp 没有事件会告诉您另一个进程已完成写入文件。
-
@Marged 如果写入过程使用文件锁,这是一个很好的解决方案。锁定机制只是建议性的;如果锁存在,应用程序可以保证检测到锁,但不能保证防止并发修改。
-
@erickson - 这不是一个好的解决方案,因为无法判断文件的文件传输是否完成并且没有失败。唯一知道传输成功的是发送方,因此需要向接收端发送一些传输成功完成的信号。
标签: java filesystems race-condition polling