编辑问题:我正在研究多线程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消息的数量吗?
同样在上面两个接近哪一个更好?
答案 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格式错误或无效,您不想回滚您的交易。您可能希望记录错误,但是您已成功处理该消息,这只是“成功”,这意味着您已将消息标识为有问题。
另一方面,如果在处理由消息外部事件(例如数据库已关闭或目标主题不可用)引起的消息时出现问题,您可能确实想要回滚事务,但是你也想确保在问题解决之前停止使用消息,否则你最终会得到你所描述的场景,你不断地反复处理相同的消息,并且每当你尝试访问任何资源时都会失败。目前无法使用。