共享文件系统主从
共享文件系统主从
如果您拥有 SAN 或共享文件系统,则可以使用它来提供高可用性,这样如果一个代理被终止,另一个代理可以立即接管。
确保您的共享文件锁正常工作
请注意,此故障转移系统的要求是分布式文件系统,例如 SAN,其独占文件锁能够可靠地工作。如果您没有这样的系统可用,请考虑使用主从,它实现了类似的功能,但使用 ActiveMQ Classic 进行复制的本地文件系统,在商品硬件上工作。
OCFS2 警告
使用 OCFS2 进行测试时,两个代理都认为自己拥有主锁 - 这是因为“OCFS2 仅支持使用“fcntl”进行锁定,而不支持“lockf 和 flock”,因此 Java 中的互斥文件锁定不受支持。”
来自 http://sources.redhat.com/cluster/faq.html#gfs_vs_ocfs2
OCFS2:没有集群感知的 flock 或 POSIX 锁
GFS:完全支持集群范围的 flock 和 POSIX 锁,并且得到支持。
有关更多讨论,请参见此 JIRA:https://issues.apache.org/jira/browse/AMQ-4378NFSv3 警告
如果 NFSv3 客户端异常终止(即 ActiveMQ Classic 主代理),NFSv3 服务器将不会超时该客户端持有的锁。这实际上使 ActiveMQ Classic 数据目录不可访问,因为 ActiveMQ Classic 从代理无法获取锁,因此无法启动。使用 NFSv3 解决此困境的唯一方法是重新启动所有 ActiveMQ Classic 实例以重置所有内容。
使用 NFSv4 是另一种解决方案,因为其设计包括锁超时。当使用 NFSv4 并且持有锁的客户端出现异常终止时,根据设计,该锁将在 30 秒后释放,允许另一个客户端获取该锁。有关此内容的更多信息,请参见此博客文章。
基本上,您可以从同一个共享文件系统目录运行任意数量的代理。第一个获取该文件独占锁的代理为主代理。如果该代理死亡并释放了锁,则另一个代理接管。从代理坐在一个循环中,试图从主代理获取锁。
以下示例显示了如何为共享文件系统主从配置代理,其中 /sharedFileSystem 是共享文件系统上的某个目录。这仅仅是配置基于文件的存储以使用共享目录。
<persistenceAdapter>
<kahaDB directory="/sharedFileSystem/sharedBrokerData"/>
</persistenceAdapter>
或
<persistenceAdapter>
<levelDB directory="/sharedFileSystem/sharedBrokerData"/>
</persistenceAdapter>
或
<persistenceAdapter>
<amqPersistenceAdapter directory="/sharedFileSystem/sharedBrokerData"/>
</persistenceAdapter>
启动
启动时,一个主代理获取对代理文件目录的独占锁 - 所有其他代理都是从代理,并暂停等待独占锁。
客户端应使用 故障转移传输 连接到可用的代理。例如,使用类似以下内容的 URL
failover:(tcp://broker1:61616,tcp://broker2:61616,tcp://broker3:61616)
只有主代理启动其传输连接器,因此客户端只能连接到主代理。
主代理故障
如果主代理丢失独占锁,则它会立即关闭。如果主代理关闭或发生故障,另一个从代理将获取锁,因此拓扑结构将切换到以下图表
另一个从代理立即获取文件系统的独占锁,因此它们开始成为主代理,启动其所有传输连接器。
客户端断开与已停止的主代理的连接,然后故障转移传输尝试连接到可用的代理 - 其中只有一个可用,即新的主代理。
主代理重启
在任何时候,您都可以重新启动其他代理,这些代理加入集群并作为从代理启动,等待成为主代理(如果主代理关闭或发生故障)。因此,在重新启动旧主代理后,将创建以下拓扑结构…
调度程序支持
ActiveMQ Classic 维护有关调度的信息,这些信息独立于持久性适配器中的设置。因此,对于共享文件系统,重要的是明确告诉 ActiveMQ Classic 在哪里存储调度程序信息。为此,请在 broker
上设置 dataDirectory
属性,例如
<broker xmlns="https://activemq.apache.org/schema/core"
dataDirectory="/some/location"
brokerName="mmuserb2" useJmx="true" advisorySupport="false"
persistent="true" deleteAllMessagesOnStartup="false"
useShutdownHook="false" schedulerSupport="true">