JMS事务如何与并发使用者一起工作?

时间:2015-11-10 18:48:03

标签: java jms ibm-mq messaging

嘿所以我有一个需要顺序处理的消息队列。现在这个处理涉及调用Web服务(有时可能会关闭),所以我必须使消息检索事务性。据我所知,当中途发生任何异常时,整个交易回滚,消息不会丢失吗?

但是还需要消息使用者的高可用性,所以我有两个监听器实例在我的队列中监听。现在,事务是否确保第二条消息不被侦听器的另一个实例检索,直到第一条消息完全处理完第一条消息为止?或者我还需要做些什么来确保在完成处理之前没有消息从队列中发出。

如果需要任何其他配置,它是在MQ中还是在侦听器上?

我使用websphere mq作为消息代理和spring集成来检索消息。谢谢您的帮助。

修改

使用令牌事物首先要关注的是队列管理器本身的高可用性。保存此标记的队列必须是某个队列管理器的一部分。现在,如果我们有故障转移,则将无法再访问该控制队列。哪种方式意味着我们需要在故障转移时准备好另一个控制队列。

我们不能让侦听器在正常操作期间侦听该DR控制队列。 (假设我们有一种机制可以确保"数据"队列完全复制)。侦听器实例应该知道已启动故障转移,以便它可以在正常操作期间停止侦听控制队列并切换到辅助节点。我不能仅使用侦听器实例来执行此操作。将消息放入队列的实际生产者必须通知侦听器实例停止侦听正常的操作控制队列并切换到辅助节点。如果存在任何中间连接问题(并且正常的操作队列管理器确实没有发生故障),这将是一个棘手的问题,但这种情况太多了。

由于控制队列的高可用性,我们在低负载情况下遇到与非可共享相同的问题。现在我们偶尔会出现负载峰值,但是会有萧条时期。 (在夜间和东西)。这个令牌系统真的没有反应性吗?这更像是周期性的事情。所以,让我们说几个小时内我们都没有收到任何消息。侦听器仍将不断检查队列,因为令牌消息一直触发一个实例。这或多或少使它真正成为一个投影者。我可能还有多个监听器实例,每个轮询在一小时的不同时间进行轮询吧?它本身并不是事件驱动的。

第三个真的是插入令牌消息的问题。在首次安装或故障恢复期间,我们将手动插入此令牌的额外手动步骤(因为令牌有时会在故障转移中丢失)。我们无法真正使其中一个侦听器实例执行此操作,因为如果侦听器实例未找到该消息,则意味着某个其他侦听器实例具有该令牌。所以这个逻辑必须是分开的。如果我们实际上将一些有意义的信息放入此令牌消息中,则必须是必须触发的实用程序,而不是通过UI插入。

我认为第一个和第三个并不是真正的问题,但只是额外的开销,如果我们进行轮询实现则不需要。第二个是困扰我的最重要的事情。

3 个答案:

答案 0 :(得分:1)

你需要传递令牌。以下是它的工作原理:

首先,创建第二个队列并在其中放置一条消息。现在使用以下逻辑启动每个程序。

  1. 使用无限制或较长的等待时间间隔以及FAIL_IF_QUIESCING选项从同步点下的令牌队列中获取令牌消息。
  2. 将令牌消息放回同一个UOW中的令牌队列。
  3. 在相同的UOW下从应用程序队列中获取下一条消息。
  4. 正常处理应用程序的消息。
  5. 承诺发展。
  6. 您可以根据需要使用任意数量的应用实例。您将在每个应用程序实例的两个队列中的每个队列上看到一个输入句柄。由于独占使用队列,任何app实例都不必处理错误。

    由于只有一个令牌消息,并且一次只有一个应用程序可以将其保存在同步点下,因此只有一个应用程序可以主动处理应用程序消息。由于应用程序队列的GET取决于令牌队列中成功的GET,所以所有应用程序消息都按严格顺序处理。

    注意:应用程序将使用与令牌队列上的令牌消息一样多的并发线程来处理应用程序消息。如果有人曾向令牌队列添加另一个令牌消息,则会丢失严格的序列处理。因此,不得向除app app帐户以外的任何人授予对该队列的读/写访问权限。此外,该令牌消息的结构通常是应用程序可以识别它。如果有一个混乱的无关消息落在那里,应用程序应该忽略它并发出警告。

    您会在两个应用之间看到相当均匀的消息分布。如果您使用两个以上的应用程序,您可能会看到一个非常 un 均匀分布,因为队列句柄是在堆栈中管理的。当一个实例提交它的UOW时,下一个实例的句柄位于堆栈的顶部,因此它获得下一条消息。在处理该消息时,刚刚提交的实例将其GET置于堆栈顶部。如果您有3个或更多的监听实例,则只有前两个会看到任何流量。

    这可确保一次一个地从队列中处理消息。它 确保您不会获得欺骗。

    如果您在同步点下执行所有操作,则不会丢失任何消息。但是,在检索和处理消息的情况下,COMMIT调用失败。在这种情况下,事务将回滚,同一消息再次可用。如果您使用的是1阶段提交而不是XA,则不会回滚该消息的处理。

    好消息是,令牌消息也将处于同步点下,并修复了孤立客户端通道需要一段时间才能释放事务的问题。新连接将获得比孤立事务在同步点下保留的消息更旧的消息。最终,通道代理超时将消息释放回队列,但有效地将其位置更改为隐藏在隔离时处理的任何消息。

    在这种情况下,令牌消息也会被隔离,因此在此类连接丢失消息处理暂时停止并等待通道代理超时后。如果发生这种情况,只需在具有UOW的实例上发出STOP CHANNEL命令。

    根据此答案特定的其他问题详情进行更新

      

    保存此令牌的队列必须是某个队列管理器的一部分。   现在,如果我们有故障转移,那么该控制队列将不再存在   无障碍。哪种意味着我们需要另一个控制队列   在发生故障转移时准备就绪。

    令牌队列与应用程序队列一样可用或不可用。只需要一个。如果应用程序需要HA,则应使用多实例QMgr或硬件HA群集。这些共享磁盘使故障转移中出现的QMgr与应用程序连接的QMgr相同,只是位于不同的物理位置。

    如果应用需要DR,则可以将QMgr的日志和数据目录下的磁盘复制到DR站点。但是,在主数据中心进行处理时,不应该监听这些实例。

      

    侦听器实例应该知道故障转移已经启动了   它可以在正常操作期间停止监听控制队列   切换到辅助。我不能使用听众这样做   仅有实例。

    为什么不呢? WMQ在很长一段时间内都有可重新连接的客户端,而v7.0.1中的多实例功能使得重新连接丢弃简单。作为管理员,您的工作是确保只有一个应用程序实例和令牌(非触发!)队列可用。在中断期间,客户端将重试,无需任何应用程序代码来驱动它。它可以找到任何一个实例并连接起来。

      

    将消息放入队列的实际生产者必须这样做   通知侦听器实例停止侦听正常操作   控制队列并切换到辅助队列。

    问题是与并发消费者的序列化。这是关于生产者和消费者必须在共同位置会合的设计。碰巧与此重叠的不同问题只是因为序列化有些复杂。如果您需要探索拓扑,请提出其他问题。

      

    这个令牌系统并不是真的   反应对吗?这更像是周期性的事情。所以,让我们说我们不会得到   任何消息几个小时。听众仍然会不断   检查队列因为令牌消息一直触发一个实例   接下来。

    这不使用触发。它使用令牌(不是触发器!)消息,就像文件系统或数据库使用锁的方式一样,以便于序列化。无论哪个侦听器获取令牌消息,然后在应用程序队列上进行无限制等待。其他侦听器对令牌(不是触发器!)队列进行无限制等待。基本上,他们闲置着,直到消息到来。零重新连接,零轮询,零CPU周期。如果您需要知道它们还活着,请让它们暂时在应用程序队列上超时。这将在令牌队列上回滚它们的UOW,令牌队列将令牌传递给另一个侦听器。

      

    第三个真的是插入令牌消息的问题。   在首次安装或故障恢复期间,我们会有额外的安装   手动插入此令牌的手动步骤(因为令牌将是   有时会在故障转移中丢失)。

    为什么呢?您是否经常在同步点下遇到MQ丢失持久性消息?如果是这样,你做错了。 ;-)在具有严格序列化要求的情况下,只能有一个队列的活动实例。如果由于某种原因,除了通过磁盘复制之外还有预定义的应用程序队列的其他实例,则会有一个令牌(不是触发!)队列的实例也预定义在它旁边,并且每个队列中都有一个令牌(不是触发!)消息等待队列。当然,没有人会在严格的消息顺序要求下做这样的事情,但是如果他们这样做了,那么这些队列肯定会在不使用时被禁用。

      

    我们无法真正成为听众之一   实例执行它,因为如果侦听器实例没有找到该消息   它有点意味着其他一些侦听器实例具有令牌。

    正确。侦听器可以检查队列深度,事务,输入句柄等,但通常明智的做法是避免将应用程序逻辑与控制逻辑混合。

      

    所以   这个逻辑必须是分开的。如果我们真的把一些有意义的东西   对此令牌消息的信息,它必须是必须的实用程序   触发而不是通过UI插入。

    为什么呢?你的程序员处理应用程序消息中的结构化数据,对吧?如果这被认为更加困难,那么有人做错了。 ;-)将一个格式化令牌(不是触发!)消息的实例写入队列,然后将其卸载到文件中。当您需要重新初始化队列时,请使用Q或QLoad首先清除队列,然后将文件加载到队列中。 那个实用程序将是在执行其魔法之前打开队列以供独占使用,检查深度,检查句柄等的实用程序。当我为咨询客户端执行此操作时,我通常会定义一个在MQ启动上初始化队列的服务,并且还在应用程序GUI中为操作和支持人员提供一个功能。只要管理令牌(非触发器)队列的应用程序在这些操作期间获得独占访问权限,它的确如何完成或控制应用程序的实例数量并不重要。

    作为一项规则,我还使用消息中的结构向侦听器发送命令。有真正的令牌消息,然后有消息指示应用程序实例执行操作。例如,拥有一个非事务性的" ping"非常好。能力。我是否在单个UOW中删除令牌(不是触发!)队列上的ping消息比我有app实例监听的更多ping消息,我保证会联系所有人。通过这种方式,我可以检测到僵尸。根据需要多少检测,监听器可以通过在日志,控制台,事件队列等中提供状态(正常运行时间,处理消息等)来对ping做出反应。

      

    我猜第一个和第三个并不是真正的问题,但只是额外的问题   如果我们去寻找一个轮询器,就不需要开销   实施

    这很好,因为这都是非常标准的东西。问题主要在于序列化与HA / DR冲突的要求。您正在寻找的是跨多个物理位置实现单个逻辑队列的全局事务原子性。虽然WAS消息传递引擎有,但IBM MQ从未试图提供这种功能。最接近的MQ是使用两个MQ设备,具有消息和事务数据的内存到内存复制,但是在光速延迟开始显着影响吞吐量之前,这只有几英里。它无法满足您的灾难恢复需求。实际上,如果您希望DR数据中心的恢复点为零,则 nothing 缺少同步复制。

答案 1 :(得分:0)

关于你的医管局问题......

如果您从一个队列中读取了两个队列接收器,我就不知道任何自然的方法来避免它们之间的并行性。

也许某些特定于供应商的功能,但这似乎有点奇怪,我不会有很高的期望。

答案 2 :(得分:0)

如果您在同步点下处理消息,则可以回滚事务,以便在发生错误时将已处理的消息放回输入队列。 如果程序异常结束,则会发生隐式退出。

http://www-01.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.dev.doc/q026800_.htm?lang=en

消息的事务处理不会阻止两个单独的消费者同时阅读消息。 队列中有一个名为Shareability的属性,可以将其设置为Not Shareable,以防止队列同时由不同的使用者打开。 您应该使用此选项并准备应用程序以重试打开队列,以便在第一个实例失败时,第二个实例将打开队列。