【问题标题】:IBM MQ Client: Should I commit after each Get to prevent other clients receiving same messageIBM MQ 客户端:我是否应该在每次 Get 后提交以防止其他客户端收到相同的消息
【发布时间】:2020-12-17 18:10:35
【问题描述】:

我的 C# 应用程序只从 IBM MQ(9.x 版)读取消息。我调用MQQueueManagerAccessQueue()方法,然后调用MQQueue.Get(),循环读取消息并最终调用queue.Close()

我找不到明确的信息是否应该在每条消息之后(或在queue.Close() 之前或之前)调用MQQueueManager.Commit(),以确保处理的消息不会被另一个客户端第二次使用,它连接到同一个queueName .有人可以帮我澄清一下吗?

这里是消息选项:MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING

并打开选项:MQC.MQSO_FAIL_IF_QUIESCING | MQC.MQSO_MANAGED | MQC.MQSO_NON_DURABLE | MQC.MQOO_INPUT_AS_Q_DEF

【问题讨论】:

  • 您需要在 SYNC_POINT 下获取消息。如果在 SYNC_POINT 下接收到消息,则在收到消息的应用程序使用 Rollback 调用将其回滚之前,其他人将无法使用该消息。如果您调用 Comit,该消息将从队列中删除。

标签: c# ibm-mq


【解决方案1】:

为什么您使用MQSO 选项作为队列有点令人困惑(SO = 订阅选项),但是这些只是按位运算,因此您将获得等效的MQOO 选项的结果同样MQSO。见下文:

Bits Options Sub Options Equivalent Open Options
0x00000000 MQSO_NONE MQSO_NON_DURABLE MQSO_READ_AHEAD_AS_Q_DEF MQOO_BIND_AS_Q_DEF MQOO_READ_AHEAD_AS_Q_DEF
0x00000001 MQSO_ALTER MQOO_INPUT_AS_Q_DEF
0x00000020 MQSO_MANAGED MQOO_INQUIRE
0x00002000 MQSO_FAIL_IF_QUIESCING MQOO_FAIL_IF_QUIESCING

这意味着您正在使用以下选项打开队列:

MQOO_BIND_AS_Q_DEF | MQOO_READ_AHEAD_AS_Q_DEF | MQOO_INPUT_AS_Q_DEF | MQOO_INQUIRE |MQOO_FAIL_IF_QUIESCING

这可能是你想要的,也可能不是,但如果没有别的,你目前是如何拥有它的非常不清楚。


仅当您在同步点下执行 GET 时才需要提交。这意味着您将在“获取消息选项”中添加 MQGMO_SYNCPOINTMQGMO_SYNCPOINT_IF_PERSISTENT。如果您要执行此操作,则在您发出 MQQueueManager.Commit() 之前,消息不会完全从队列中删除,这并不意味着其他实例能够同时读取它们,但如果发生以下情况之一,则消息将返回到可供应用程序的另一个实例读取的队列中:

  • 应用程序崩溃
  • 应用程序与队列管理器断开连接
  • 申请问题MQQueueManager.Backout()

当您收到没有MQGMO_SYNCPOINTMQGMO_SYNCPOINT_IF_PERSISTENT 的消息时,该消息会立即从队列中删除。应用程序的另一个实例永远无法读取该消息。


在 IBM MQ 中,您可以非破坏性地从队列中读取消息,这称为浏览队列,是使用 MQOO_BROWSE 打开队列并指定以下获取消息选项之一的结果:

  • MQGMO_BROWSE_FIRST
  • MQGMO_BROWSE_NEXT
  • MQGMO_BROWSE_MSG_UNDER_CURSOR

大多数情况下,您浏览的消息仍然可以被打开相同队列的另一个应用程序读取。但是,您也可以添加MQGMO_LOCK,这将锁定消息不被其他应用程序读取。这允许您稍后针对您锁定的消息发出破坏性 GET,有几件事会释放锁定,包括发出另一个 GET 调用。

如果您使用MQOO_INPUT* 选项之一打开队列并且未指定MQGMO_BROWSE* 选项,那么您正在破坏性地从队列中读取消息。这意味着该消息将无法供其他应用程序阅读。

您还可以使用MQGMO_SYNCPOINT 为任何消息(持久性或非持久性)(或MQGMO_SYNCPOINT_IF_PERSISTENT,如果您只希望它应用于持久性消息)发出破坏性GET,并且该消息将以单位读取工作,它不再可供其他应用程序获取,但在工作单元提交之前不会从队列中删除。


我找不到来自 IBM 的任何具体声明,其中包含以下内容:

当您收到没有 MQGMO_SYNCPOINT 或 MQGMO_SYNCPOINT_IF_PERSISTENT 的消息时,该消息会立即从队列中删除。应用程序的另一个实例永远无法读取该消息。

以下是一些共同描绘这幅画的参考资料:

IBM 知识中心页面IBM MQ>About IBM MQ>Introduction to IBM MQ

IBM MQ 提供:

  • 提供一次且仅一次的消息传递以确保消息能够承受应用程序和系统中断的服务质量

IBM 知识中心页面IBM MQ>Developing applications>Developing MQI applications with IBM MQ>Writing a procedural application for queuing>Committing and backing out units of work

提交和退出

类似地,当程序从工作单元内的队列中获取消息时,该消息将保留在队列中,直到程序提交该工作单元,但该消息不可被其他程序检索。当程序提交工作单元时,该消息将从队列中永久删除。如果程序退出工作单元,IBM MQ 会通过使消息可供其他程序检索来恢复队列。

同步点协调、同步点、工作单元

同步点协调 是工作单元在数据完整性的情况下提交或退出的过程。 在最简单的情况下,在事务结束时做出提交或撤销更改的决定。但是,应用程序在事务中的其他逻辑点同步数据更改可能更有用。这些逻辑点称为同步点(或同步点),处理两个同步点之间的一组更新的周期称为工作单元 .多个 MQGET 调用和 MQPUT 调用可以是单个工作单元的一部分。

IBM 知识中心页面IBM MQ>Developing applications>Developing MQI applications with IBM MQ>Writing a procedural application for queuing>Getting messages from a queue>Getting messages from a queue using the MQGET call

使用 MQGMO 结构指定 MQGET 选项

...

选项
在您的代码中,您可以按任意顺序选择选项;每个选项都由 Options 字段中的一个位表示。
Options 字段控件:

...

  • get 操作是否包含在工作单元中。

...

  • 消息是从队列中删除,还是仅仅浏览过

【讨论】:

  • 我对订阅与同步点模式有点困惑,是否可以在订阅模式下以每条消息由一个且只有一个客户端消费的方式消费消息。那我应该使用哪些参数?
  • 您正在打开队列而不是订阅主题。如果您正在打开一个主题的订阅,您可能会在同步点下发出gets。开放选项用于队列。订阅主题时使用订阅选项。我在我的答案中添加了一些关于不使用同步点希望能解决问题的内容。
  • 啊,所以我应该使用带有这些参数的 AccessTopic() 而不是 AccessQueue(),对吧?您能否提供一个链接,我可以在其中了解这两者之间的区别?我认为主题只是特定队列的标识符
  • 阅读 IBM 官方文档让我创建了这篇文章,因为那里的每篇文章提出的问题多于回答的问题。 > 主题用于发布/订阅。队列用于点对点。
  • 我在帖子末尾添加了一些参考资料,如果这提供了您想要的内容,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 2016-12-14
  • 2022-11-08
  • 1970-01-01
  • 2019-04-08
  • 2016-10-09
相关资源
最近更新 更多