.net XMS中的IBM-MQ阅读器逐个返回处理过的消息

本文关键字:返回 处理 消息 中的 XMS IBM-MQ net | 更新日期: 2023-09-27 18:16:07

我正在实现一个组件,该组件读取特定队列中可用的所有消息,但应该只在消息内容被处理并持久化之后才从队列中异步删除消息。我们读取消息的速度比接收消息的速度要快(例如,在准备接收第一条消息之前,我们可能已经读取了10条消息)。当前的实现使用XMS API,但如果XMS不适合这些目的,我们可以切换到MQI。

我们已经尝试了两种方法来解决这个问题,但是这两种方法都有不可接受的缺点。我希望有人能提出一个更好的方法。

第一个实现使用专用线程中的IMessageConsumer来读取所有消息并在它们可用时发布它们的内容。当消息被处理后,将调用message.Acknowledge()方法。会话以"AcknowledgeMode.ClientAcknowledge"创建。这种方法的问题在于,根据文档,这会确认(并删除)所有已接收到的未确认消息。在上面的示例中,这将意味着所有10个读消息都将被第一个调用填充。所以这并不能真正解决问题。由于我们需要读取吞吐量,我们无法真正修改此解决方案,以便在读取第二条消息之前等待第一条消息的返回,等等。

第二个实现在一个确定的线程中使用IQueueBrowser来读取所有消息并发布其内容。这不会在读取队列时将消息从队列中删除。然后,一个单独的专用线程(在BlockingQueue上)等待已处理消息的JMS消息id。对于其中的每一个,它都构造一个专用的IMessageConsumer(使用带有JMSMessageID的消息选择器)来读取并返回消息。(XMS文档队列浏览器一节建议将IQueueBrowser与专用IMessageConsumer配对。)此方法确实可以按预期工作,但是,正如人们所想象的那样,它在MQ服务器上的cpu密集程度太高。

.net XMS中的IBM-MQ阅读器逐个返回处理过的消息

问题中提出的两种方法似乎都依赖于应用程序的单个实例。使用多个应用程序实例,事务会话和COMMIT有什么问题?性能报告(这些是名称为MP**的supportpac)都表明,多个应用程序实例可以最大化吞吐量,水平扩展是您的场景中最常用的方法之一。

这样的设计要么是多个应用程序实例,要么是同一个应用程序中的多个线程。使其正确工作的关键是要记住,事务的作用域是连接句柄。这意味着多线程应用程序必须为每个连接实例分配一个单独的线程,并且消息在同一个线程中读取。

进程流是,使用事务会话,应用程序对队列执行正常的MQGet,根据需要处理消息内容,然后发出MQCommit。(我将在示例中使用MQ本机API名称,因为这与语言无关。)如果这是一个XA事务,应用程序将调用MQBegin来启动事务,但对于单阶段提交,则假定事务。在这两种情况下,MQCommit都会结束事务,从而从队列中删除消息。当消息处于同步点时,没有其他应用程序实例可以检索它们;MQ只交付下一个可用消息。如果一个事务被回滚,下一个来自任何线程的MQGet将检索它,假设FIFO交付。

有一些样品在:
[WMQ install home]'tools'dotnet'samples'cs'xms'simple'wmq'
SimpleXAConsumer.cs是XA版本的一个例子。非xa版本更简单,因为不需要外部协调器、MQBegin动词等等。如果您从其中一个实例开始,请确保它们没有指定队列的独占使用,并且您可以使用相同的配置启动多个实例。或者,选取示例中包括创建连接、消息处理、关闭连接和销毁连接的部分,并将所有这些都包装在线程生成类中。

[在这里插入关于使用最新版本类的常用建议。]