多线程JMS代码:CLIENT_ACKNOWLEDGE或事务会话

时间:2010-10-01 17:25:26

标签: java transactions jms messaging

编辑问题:我正在研究多线程JMS接收器和发布者代码(独立的多线程Java应用程序)。 MOM是MQSonic。 从队列接收XML消息,调用存储过程(执行需要70秒),并在90秒内将响应发送到Topic。 当代理关闭或应用程序处于计划关闭状态时,我需要处理一个条件。即,从队列接收消息并在java中处理消息的条件,同时Queue和Topic都将关闭。然后要处理那些不在队列中但不发送到主题但在java内存中的消息,我有以下选项:

(1)创建CLIENT_ACKNOWLEDGE会话: connection.createSession(false,javax.jms.Session.CLIENT_ACKNOWLEDGE) 这里我只会在成功完成交易(存储过程)之后才会确认消息

(2)使用事务会话,即connection.createSession(true,-1)。在这种方法中,由于事务(存储过程)中的一些异常,消息被回滚并重新传递。它们一次又一次地回滚并继续直到我杀死该程序。我可以限制从队列中重新发送jms消息的数量吗?

同样在上面两个接近哪一个更好?

4 个答案:

答案 0 :(得分:3)

界面progress.message.jclient.ConnectionFactory有一个方法setMaxDeliveryCount(java.lang.Integer value),您可以在其中设置将邮件重新传送到MessageConsumer的最大次数。当此次数达到时,它将被移动到SonicMQ.deadMessage队列。

您可以在第210页的“Sonic MQ应用程序编程指南”(7.6版)中查看。

关于哪个更好的问题...这取决于存储过程是否会多次执行。如果这是一个问题,您应该使用跨越JMS队列和数据库的事务(Sonic支持XA事务)。如果您不介意多次执行,那么当您发现代理已关闭时(当您尝试确认该消息时,我很可能),我会拒绝确认该消息并中止处理。这样,如果第一个处理器在连接失败后无法执行此操作,则另一个处理器能够处理该消息。

如果消息需要可变时间来处理,您可能还需要查看Sonic JMS会话的SINGLE_MESSAGE_ACKNOWLEDGE模式。通常,在消息上调用acknowledge()也会确认之前发送的所有消息。如果你不按顺序处理它们,那就不是你想要发生的事了。在单消息确认模式(不在JMS标准中)中,acknowledge()仅确认调用它的消息。

答案 1 :(得分:0)

在不知道您使用的是什么消息提供程序的情况下,我不知道这是否会对您有所帮助。

MQ系列消息有一个回退计数器,可以通过在队列上配置强化回退计数器选项来启用。
当我以前遇到这个问题时,我会这样做:

// get/receive message from queue

if ( backout counter > n ) {
   move_message_to_app_dead_letter_queue();
   return;
}
process_message();

MQ系列头字段可作为JMS属性访问。

如果您可以使用XA事务同时回滚或提交数据库和队列管理器,则使用上述方法也会有所帮助。 但是,XA事务会导致严重的性能损失,并且对于存储过程,这可能是不可能的。

另一种方法是将消息作为blob立即写入message_table,然后从队列中提交消息。
在message_table上放置一个触发器以调用存储的proc,然后将JMS响应机制添加到存储的proc中。

答案 2 :(得分:0)

如果您担心与可能关闭的消息队列/代理/服务器/等进行通信,以及如何中断您尝试设计的较大进程的整体流程,那么您应该查看JMS队列它支持服务器群集,因此当群集中的各个服务器出现故障时,您仍然可以可靠地生成/使用消息。

答案 3 :(得分:0)

您的问题并非100%明确,但似乎问题是您在处理邮件时会抛出异常,但实际情况并非如此。

如果邮件确实存在问题,请说根据您的数据模型,xml格式错误或无效,您不想回滚您的交易。您可能希望记录错误,但是您已成功处理该消息,这只是“成功”,这意味着您已将消息标识为有问题。

另一方面,如果在处理由消息外部事件(例如数据库已关闭或目标主题不可用)引起的消息时出现问题,您可能确实想要回滚事务,但是你也想确保在问题解决之前停止使用消息,否则你最终会得到你所描述的场景,你不断地反复处理相同的消息,并且每当你尝试访问任何资源时都会失败。目前无法使用。