我有一种情况,有两个java应用程序正在监视一个目录中的传入文件。假设有一个目录 DIR,两个 JVM 进程正在监视该目录中是否有任何扩展名为 .SGL 的文件。
我们在这里面临的问题是,有时两个节点都收到有关新文件的通知,并且两个节点都试图处理同一个文件。
通常我们使用数据库来处理这些情况,该数据库尝试插入具有唯一文件名列的表,并且只有一个会成功并继续处理。
但是对于这种情况,我们没有数据库。
处理此类问题的最佳方法是什么?我们可以依赖文件重命名解决方案吗?文件重命名是原子操作吗?
对于这种情况 Spring Integration 建议
FileSystemPersistentAcceptOnceFileListFilter
: https://docs.spring.io/spring-integration/reference/html/files.html#file-reading
- 将“看到的”文件存储在 MetadataStore 中,以便在应用程序重新启动后继续存在。
- 默认键是‘前缀’加绝对文件名;值是文件的时间戳。
- 如果文件存在于商店中并且具有
,则文件被视为已“查看”- 与当前文件的修改时间相同。
当您为所有应用程序实例共享持久性
MetadataStore
时,只有其中一个会处理该文件。所有其他人都会过滤它。
每个观察者(甚至同一 JVM 中的两个观察者)都应该始终收到添加新文件的通知。
如果你想分工,也可以
文件重命名是原子操作吗?
是的,只有一个进程可以成功重命名文件,即使两个进程都尝试重命名为相同的名称。
我们在一些经历大量文件流量的后端应用程序中使用的部分解决方案是在触发“新文件”事件(即程序通知新文件或修改文件)后引入人为延迟,并且在对所述文件进行任何实际处理之前。该延迟也必须是随机的 - 例如,从 100 到 300 毫秒。当然,除上述之外还需要某种文件锁定;但延迟处理方法可确保两个或多个应用程序不会同时跳转到该文件,从而可能导致出现竞争情况。事实上,这种方法适用于任何应用程序,而不是专门与 Java 或 Spring 相关。