【问题标题】:How to poll a directory and not hit a file-transfer race condition?如何轮询目录而不遇到文件传输竞争条件?
【发布时间】:2015-07-02 21:07:23
【问题描述】:

我正在开发一个应用程序,该应用程序以定义的时间间隔轮询目录中的新输入文件。大致流程是:

  1. 输入文件被另一个应用通过 FTP 传送到着陆带目录
  2. 我们的应用唤醒
  3. 列出输入目录中的文件
  4. 以原子方式将文件移动到单独的暂存目录
  5. 启动工作线程(通过工作分配队列)以使用暂存目录中的文件
  6. 回去睡觉

我发现了一个问题,应用程序会在输入文件不完整且仍在传输过程中提取文件,从而导致工作线程错误,需要人工干预。这是我们需要避免的情况。

我应该注意到文件传输会成功完成,服务器会得到一个完整的副本,但这会发生在应用程序因错误放弃后。

我想以一种干净的方式解决这个问题,虽然我有一些解决方案的想法,但他们都有我不喜欢的问题。

这是我考虑过的:

  1. 强制其他应用程序(其中一些是我们公司外部的)最初将输入文件传输到保存目录,然后在传输后将它们原子地移动到输入目录中。这是我有过的最有力的想法,但我不喜欢这个,因为我不相信它会永远正确实施。
  2. 重试有限次出错。我不喜欢这个,因为它是一个部分解决方案,它对可能违反的传输时间和文件大小做出了假设。它还会模糊真正坏的文件和刚刚传输不完全的文件之间的界限。
  3. 观察文件大小,如果文件大小在规定的时间段内没有改变,则只提取文件。我不喜欢这个,因为它在我们的环境中太复杂了:轮询器是一个非并发的集群 Quartz 作业,所以我不能只将这些信息保存在内存中,因为该作业可以在服务器之间反弹。我可以将它存储在 jobdetail 中,但这个解决方案感觉太复杂了。

我不是第一个遇到这个问题的人,所以我相信我会在这里得到更好的想法。

【问题讨论】:

  • 我不知道 Java 的文件/目录更新事件的工作方式是否不同,或者那些包含在 Apache Camel 中的文件系统观察程序。但我认为,如果您尝试在复制文件之前以独占方式打开文件并且失败,您应该知道写入过程尚未完成:看看这里stackoverflow.com/questions/128038/…
  • 你真的要投票吗?为什么不改用java nio watch service API
  • @Alp 没有事件会告诉您另一个进程已完成写入文件。
  • @Marged 如果写入过程使用文件锁,这是一个很好的解决方案。锁定机制只是建议性的;如果锁存在,应用程序可以保证检测到锁,但不能保证防止并发修改。
  • @erickson - 这不是一个好的解决方案,因为无法判断文件的文件传输是否完成并且没有失败。唯一知道传输成功的是发送方,因此需要向接收端发送一些传输成功完成的信号。

标签: java filesystems race-condition polling


【解决方案1】:

我曾经遇到过这种情况,我们让其他人加载具有不同扩展名的文件,例如*.tmp,然后在文件复制完成后,他们用我的代码轮询的扩展名重命名文件。不确定当文件通过 FTP 进入时,这是否很容易完成。

【讨论】:

  • 根本问题是在没有来自发送者的某种信号的情况下,没有 方法可以明确地确定文件传输是否完成并且完全成功。在文件传输后重命名文件就是这样一个信号,它可能是最容易实现的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
  • 2013-10-30
  • 1970-01-01
  • 2018-10-08
相关资源
最近更新 更多