IBM MQ 客户端:我是否应该在每次获取后提交以防止其他客户端接收相同的消息

IBM MQ Client: Should I commit after each Get to prevent other clients receiving same message

我的 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.

为什么要对队列使用 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 中,您可以 non-destructively 从队列中读取消息,这称为浏览队列,是使用 MQOO_BROWSE 打开队列并指定以下获取消息选项之一的结果:

  • MQGMO_BROWSE_FIRST
  • MQGMO_BROWSE_NEXT
  • MQGMO_BROWSE_MSG_UNDER_CURSOR

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

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

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


我找不到任何来自 IBM 的具体声明如下:

When you get a message without MQGMO_SYNCPOINT or MQGMO_SYNCPOINT_IF_PERSISTENT the message is immediately removed from the queue. The message can never be read by another instance of the application.

这里有一些共同描绘这幅画的参考资料:

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

IBM MQ provides:

  • Qualities of service that provide once and once only delivery of messages to ensure messages will withstand application and system outages

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

Commit and back out

Similarly, when a program gets a message from a queue within a unit of work, that message remains on the queue until the program commits the unit of work, but the message is not available to be retrieved by other programs. The message is permanently deleted from the queue when the program commits the unit of work. If the program backs out the unit of work, IBM MQ restores the queue by making the messages available to be retrieved by other programs.

Syncpoint coordination, syncpoint, unit of work

Syncpoint coordination is the process by which units of work are either committed or backed out with data integrity. The decision to commit or back out the changes is taken, in the simplest case, at the end of a transaction. However, it can be more useful for an application to synchronize data changes at other logical points within a transaction. These logical points are called syncpoints (or synchronization points ) and the period of processing a set of updates between two syncpoints is called a unit of work. Several MQGET calls and MQPUT calls can be part of a single unit of work.

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

Specifying MQGET options using the MQGMO structure

...

Options
Within your code, you can select the options in any order; each option is represented by a bit in the Options field.
The Options field controls:

...

  • Whether the get operation is included in a unit of work.

...

  • Whether the message is removed from the queue, or merely browsed