Java集群,运行只任务一次
Java cluster, run task only once
我们有一个 java 进程,它使用 apache commons vfs 侦听文件系统上的目录 X。每当将新文件导出到此目录时,我们的流程就会启动。我们首先将文件重命名为 filename.processing 并解析文件名,从文件中获取一些信息并插入表中,然后再将此文件发送到 Document管理系统。这是每个集群的单线程应用程序。
现在在集群环境中考虑这个 运行ning,我们有 5 个服务器。所以 5 个不同的 VM 正在尝试访问同一个文件。整个实现的基础是在给定时间只有一个进程可以将文件重命名为 .processing,因为 OS 不允许多个进程同时修改文件。一旦集群获取并重命名文件为.processing,其他集群将忽略格式为.processing 的文件。
一年多以来一直运行良好,但现在我们几乎没有发现重复项。看起来多个集群都获得了文件,在这种情况下,集群 a、b、c 获得了文件 f.pdf 的访问权限,并且他们同时将其重命名为 f.pdf.processing,(我仍然对 OS 如何允许同时修改文件感到困惑)。结果,集群 a、b、c 处理了文件并将其发送到文档管理系统。所以现在有3个重复文件。
所以简而言之,我所关注的是,在集群环境中仅执行一次 运行 任务。我还希望它有一个故障转移机制,这样如果集群出现问题,另一个集群就会接手这个任务。我们不想设置 env 变量,比如在一个盒子上设置 master=true,因为这会将它限制在一个集群中,并且不会处理故障转移。
感谢任何形式的帮助。
参见以下关于文件锁定的post:How do filesystems handle concurrent read/write?
文件的读写操作(包括重命名)不是原子的,并且进程之间的同步也不是很好,正如您假设的那样 - 至少在大多数操作系统上不是这样。
但是,创建新文件通常是一个原子操作。你可以利用它来发挥你的优势。这个概念叫做全文件锁定。
在将文件重命名为 .processing 之前,您是否尝试使用 FileLock tryLock() 或 lock()?如果你没有,我想你应该试试,所以在这种情况下,只有一个应用程序可以允许更改此文件。
更新:对不起,我忘了你问的是VDF。在 Apache VDF 中(事实上,在 Apache Synapse) I found VFSUtils class 中,有以下方法:
public static boolean acquireLock(org.apache.commons.vfs2.FileSystemManager fsManager,
org.apache.commons.vfs2.FileObject fo)
Acquires a file item lock before processing the item, guaranteing that the file is not processed while it is being uploaded and/or the item is not processed by two listeners
Parameters:
fsManager - used to resolve the processing file
fo - representing the processign file item
Returns:
boolean true if the lock has been acquired or false if not
我认为,该方法可以解决您的问题(如果您可以在您的项目中使用 Apache Synapse)。
我们正在应用程序数据库中使用共享锁 table 实现我们自己的同步逻辑。这允许所有集群节点在实际启动作业之前检查作业是否已经 运行。
我们有一个 java 进程,它使用 apache commons vfs 侦听文件系统上的目录 X。每当将新文件导出到此目录时,我们的流程就会启动。我们首先将文件重命名为 filename.processing 并解析文件名,从文件中获取一些信息并插入表中,然后再将此文件发送到 Document管理系统。这是每个集群的单线程应用程序。 现在在集群环境中考虑这个 运行ning,我们有 5 个服务器。所以 5 个不同的 VM 正在尝试访问同一个文件。整个实现的基础是在给定时间只有一个进程可以将文件重命名为 .processing,因为 OS 不允许多个进程同时修改文件。一旦集群获取并重命名文件为.processing,其他集群将忽略格式为.processing 的文件。
一年多以来一直运行良好,但现在我们几乎没有发现重复项。看起来多个集群都获得了文件,在这种情况下,集群 a、b、c 获得了文件 f.pdf 的访问权限,并且他们同时将其重命名为 f.pdf.processing,(我仍然对 OS 如何允许同时修改文件感到困惑)。结果,集群 a、b、c 处理了文件并将其发送到文档管理系统。所以现在有3个重复文件。
所以简而言之,我所关注的是,在集群环境中仅执行一次 运行 任务。我还希望它有一个故障转移机制,这样如果集群出现问题,另一个集群就会接手这个任务。我们不想设置 env 变量,比如在一个盒子上设置 master=true,因为这会将它限制在一个集群中,并且不会处理故障转移。
感谢任何形式的帮助。
参见以下关于文件锁定的post:How do filesystems handle concurrent read/write?
文件的读写操作(包括重命名)不是原子的,并且进程之间的同步也不是很好,正如您假设的那样 - 至少在大多数操作系统上不是这样。
但是,创建新文件通常是一个原子操作。你可以利用它来发挥你的优势。这个概念叫做全文件锁定。
在将文件重命名为 .processing 之前,您是否尝试使用 FileLock tryLock() 或 lock()?如果你没有,我想你应该试试,所以在这种情况下,只有一个应用程序可以允许更改此文件。
更新:对不起,我忘了你问的是VDF。在 Apache VDF 中(事实上,在 Apache Synapse) I found VFSUtils class 中,有以下方法:
public static boolean acquireLock(org.apache.commons.vfs2.FileSystemManager fsManager,
org.apache.commons.vfs2.FileObject fo)
Acquires a file item lock before processing the item, guaranteing that the file is not processed while it is being uploaded and/or the item is not processed by two listeners
Parameters:
fsManager - used to resolve the processing file
fo - representing the processign file item
Returns:
boolean true if the lock has been acquired or false if not
我认为,该方法可以解决您的问题(如果您可以在您的项目中使用 Apache Synapse)。
我们正在应用程序数据库中使用共享锁 table 实现我们自己的同步逻辑。这允许所有集群节点在实际启动作业之前检查作业是否已经 运行。