您需要传递令牌。以下是操作方法:
首先,创建第二个队列并放置单个消息。现在使用以下逻辑启动每个程序。
1. 使用无限或长等待间隔和FAIL_IF_QUIESCING选项从令牌队列中同步点获取令牌消息。
2. 将令牌消息在同一UOW中放回到令牌队列中。
3. 在相同的UOW下从应用程序队列中获取下一个消息。
4. 正常处理应用程序的消息。
5. 提交UOW。
您可以使用尽可能多的应用程序实例。每个应用实例上的两个队列将各有一个输入句柄。没有应用程序实例必须处理由于队列的独占使用而导致的错误。
由于只有一个令牌消息和一次只能有一个应用程序在同步点下持有它,因此只有一个应用程序可以主动处理应用程序消息。由于GET来源app队列取决于成功GET来源token队列,因此所有应用程序消息都按严格顺序处理。
注意:应用程序将使用与令牌队列上的令牌消息数量相同的并发线程处理应用程序消息。 如果有人向令牌队列添加另一个令牌消息,则会丢失严格的顺序处理。 因此,不应授予任何人员除应用服务帐户以外的对该队列的读/写访问权限。 此外,通常情况下,令牌消息的结构化使得应用程序可以识别它。 如果一个偶然的无关消息落在那里,应用程序应该忽略它并抛出警告。
您将看到两个应用程序之间的消息分布相当均匀。 如果您使用超过两个应用程序,则可能会看到极不均匀的分布,因为队列句柄是在堆栈中管理的。 当一个实例提交其UOW时,下一个实例的句柄位于堆栈顶部,因此它获得下一个消息。 当它处理该消息时,刚刚提交的实例将其GET放置在堆栈顶部。 如果您有3个或更多的侦听实例,则只有前两个实例会看到任何流量。
这确保了消息逐个从队列中处理。 它不能保证您不会获得重复项。
如果您在同步点下完成所有操作,就不会丢失任何消息。但是,在某些情况下,当检索和处理消息后,
COMMIT
调用失败。此时,事务将回滚,并且相同的消息再次可用。如果您使用单阶段提交而不是XA,则该消息的处理不会回滚。
好处在于令牌消息也将在同步点下,这解决了孤立的客户端通道需要一段时间才能释放事务的问题。新连接将获取早于由孤立事务保留的消息的消息。最终,通道代理超时将消息释放回队列,但实际上将其位置更改为在被隔离期间处理的任何消息之后。
在这种情况下,令牌消息也被隔离,因此在此类型的连接丢失消息处理暂停并等待通道代理超时。如果发生这种情况,只需在具有UOW的实例上发出
STOP CHANNEL
命令即可。
根据对此答案的详细问题描述进行更新
持有此令牌的队列必须是某个队列管理器的一部分。如果我们有故障转移,那么该控制队列将不再可访问。这意味着我们需要在故障转移时准备另一个控制队列。
令牌队列与应用程序队列一样可用或不可用。只需要一个。如果应用程序需要HA,则应使用多实例QM或硬件HA群集。这些共享磁盘,因此在故障转移中启动的QMgr与应用程序连接到同一物理位置的QMgr相同。
如果应用程序需要DR,则可以将QMgr日志和数据目录下的磁盘复制到DR站点。但是,在主数据中心进行处理时,这些实例上不应有任何内容正在侦听。
监听程序实例应知道故障转移已启动,以便在正常操作期间停止侦听控制队列并切换到辅助队列。我不能仅使用监听器实例来完成此操作。
Why not? WMQ早就拥有可重新连接的客户端,而v7.0.1中的多实例功能使重新连接变得非常简单。 作为管理员,您的工作是确保应用程序和令牌(而不是触发器!)队列只有一个实例可用。 在停机期间,客户端会进行重试,而无需驱动任何应用程序代码。 它找到正在运行的实例并进行连接。
将消息放入队列的实际生产者必须通知监听器实例停止监听正常操作控制队列并切换到辅助队列。
问题涉及并发消费者的序列化。这是一个设计问题,其中生产者和消费者必须在一个公共位置会合。不同的问题只是在某种程度上由于序列化而变得复杂。如果需要探索拓扑结构,请提出不同的问题。
这个令牌系统不是真正的反应性吧?它更像是定期的东西。所以假设我们几个小时都没有收到任何消息。听众仍将不断检查队列,因为令牌消息一直在触发一个接一个的实例。
这不使用触发器,而是使用令牌(不是触发器!)消息,就像文件系统或数据库使用锁一样,以促进序列化。无论哪个侦听器得到令牌消息,都会对应用程序队列进行无限等待的获取操作,而其他侦听器则在令牌(不是触发器!)队列上进行无限等待的获取操作。基本上,它们闲置着,直到有消息到达。零重新连接,零轮询,零 CPU 循环。如果需要知道它们是否存活,请让它们偶尔在应用程序队列上超时。这将回滚其在令牌队列上的 UOW,从而将令牌传递给另一个侦听器。
第三个问题实际上是关于插入令牌消息的问题。
在第一次安装或退回时,我们需要手动插入此令牌 (因为在故障转移中令牌有时会丢失)。
为什么?你是否经常遇到 MQ 在同步点下丢失持久消息?如果是这样的话,你做错了。在需要严格串行化的情况下,只能有一个队列的活动实例。如果出于某些原因已经预定义了除磁盘复制之外的应用程序队列的其他实例,则还会预定义一个令牌(而不是触发器!)队列,并在每个队列中等待一个令牌(而不是触发器!)消息。当然,如果在要求严格消息顺序的情况下有人这样做,那么这些队列肯定会在不使用时被禁用。
“我们不能让其中一个监听器实例来执行它,因为如果一个监听器实例找不到消息,那意味着其他监听器实例拥有令牌。”
正确。监听器可以检查队列深度、事务、输入句柄等,但通常最好避免将应用程序逻辑与控制逻辑混合。
“因此,这个逻辑必须是单独的。如果我们真正把一些有意义的信息放入这个令牌消息中,那它必须是一个必须通过触发器而不是通过 UI 插入的实用程序。”
为什么?你的编程人员处理应用消息中的结构化数据,对吗?如果这被认为是非常困难的话,那一定是有人做错了。;-) 写一个格式化令牌(不是触发器!)消息实例到队列,然后将其卸载到文件中。当您需要重新初始化队列时,请使用 Q 或 QLoad 首先清除队列,然后将文件加载到其中。
那个实用程序将打开队列以独占方式使用,在执行其操作之前检查深度、句柄等。当我为咨询客户执行此操作时,通常会定义一个服务,在 MQ 启动时初始化队列,并在应用程序 GUI 中为运营和支持人员提供功能。只要管理令牌(而不是触发器)队列的应用程序在这些操作期间获得它以进行独占访问,那么它的执行方式或控制应用程序的实例数量就无关紧要了。
作为惯例,我还使用消息中的结构向侦听器发送命令。有真正的令牌消息,还有命令应用程序实例执行任务的消息。例如,具有非事务性“ping”功能非常棒。如果在单个UOW中将更多的ping消息放入令牌(不是触发器!)队列中,而不是正在侦听的应用程序实例,则可以确保联系到它们所有人。通过这种方式,我可以检测僵尸程序。根据所需的仪表化程度,侦听器可以通过记录、控制台、事件队列等方式响应ping并提供状态(正常运行时间、处理的消息数量等)。
我猜第一个和第三个问题并不是真正的问题,只是额外的开销,如果我们选择轮询实现,则不需要它们。
这很好,因为这都是非常标准的东西。问题主要在于序列化要求与HA / DR的要求冲突。您要寻找的是全局事务原子性,以在多个物理位置上实现单个逻辑队列。IBM MQ从未尝试过提供此功能,但WAS Messaging Engine有。MQ最接近的方法是使用两个MQ设备,并将消息和事务数据在内存到内存之间进行复制,但仅适用于轻微延迟,否则会显着影响吞吐量。它无法处理您的DR需求。实际上,除了同步复制外,没有任何东西可以在DR数据中心实现零恢复点。