管理JMS消息到多个服务器的传递

时间:2018-08-15 00:14:01

标签: java spring jms tibco tibco-ems

我们的应用程序通过Tibco使用Spring Boot和JMS消息。我们有两个同时运行和处理消息的生产服务器。服务器正在侦听同一队列。每个服务器有10个并发侦听器。我不希望两个服务器同时处理相同的消息。没有什么可以阻止我们的队列中有重复的消息,就像我们可以在队列中有消息A的两个副本一样。如果队列中的消息是:A,A,B,C,D,则如果第一个A传递到server1,第二个A传递到server2,并且两个服务器同时处理A,那么它们就有机会创建重复项实体。我想找到一种将所有A消息发送到仅一台服务器的方法。我不能使用消息选择器b / c,因为两个服务器上都运行着相同的代码库。这就是我正在考虑的:

根据消息,在标题中设置属性。一旦将消息传递到process()方法(取决于正在处理该消息的服务器),就可以丢弃该消息,简单地返回该消息或处理该消息并进行确认。该解决方案的问题在于,由于我们需要动态地找出正在处理消息的服务器,因此服务器名称需要进行硬编码,这意味着如果服务器移动了,代码就会中断!

“目标”字段是其他可行的解决方案。

https://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/jms.html

  

目的地(如ConnectionFactories)是JMS管理的对象   可以在JNDI中存储和检索。配置弹簧时   您可以使用JNDI工厂类的应用程序上下文   JndiObjectFactoryBean /执行依赖   注入对象对JMS目标的引用。

这是我以前从未做过的事情。无论如何,是否要配置它选择正确的服务器以将消息路由到的目标?意思是,如果应该将message1传递到server1,那么它甚至都不会传递到server2,而是一直保留在队列中,直到server1使用它为止。

还有什么其他方法可以实现呢?

编辑:

我仍然不知道将某些消息仅发送到一台服务器进行处理的最佳方法是什么,但是,接受了使用数据库作为验证的响应,这就是我们认为避免处理时创建重复实体的原因数据。

2 个答案:

答案 0 :(得分:0)

我认为使用JMS目的地的想法并非一帆风顺,因为JMS规范中没有任何内容可以保证目的地和代理之间的任何类型的链接。目标只是对提供程序特定的队列/主题名称的封装。

这里的底线是,您首先需要防止重复的消息,或者可以采取某种方式来协调使用者以将它们从队列中取出来处理重复的消息。我认为您可以使用外部系统(例如数据库)来执行上述任一操作,例如:

  • 在生成消息时,请检查数据库是否有消息已发送的指示。如果找不到指示,则将记录写入数据库(将需要使用主键来防止重复)并发送消息。否则,请勿发送邮件。
  • 使用该消息时,请检查数据库,以指示该消息已经(或已经)被使用。如果未找到指示,则将记录写入数据库(将需要使用主键来防止重复)并处理消息。否则,只需确认消息而不进行处理即可。

答案 1 :(得分:0)

我建议使用“发布数据库同步”的替代方法。

按原样保留服务器和侦听器,并在主题上广播所有已处理的消息。对于刚刚启动的服务器,您可以使用“持久订阅者”来保留任何消息。

如果广播消息A,B,C等的每个处理的开始和结束,并考虑添加一点暂停(以毫为单位),则应避免冲突。这是当然的主要风险。

我不清楚您是否应该在消息处理的开始或结束时对重复处理进行验证...这取决于您的需求。

如果不能接受整个想法,那么数据库验证可能是唯一的选择,但是正如上面的评论所述,我担心会扩展。