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



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

根据消息,在标头中设置属性。消息传递到 process(( 方法后,根据哪个服务器正在处理消息,要么丢弃,只需返回消息,要么处理消息并确认它。这个解决方案的问题在于,由于我们需要动态找出哪个服务器正在处理消息,因此需要对服务器名称进行硬编码,这意味着如果服务器移动,代码就会中断!

其他可能有效的解决方案是"目标"字段。

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

目标,如连接工厂,是 JMS 管理的对象 可以在 JNDI 中存储和检索。配置弹簧时 可以使用 JNDI 工厂类的应用程序上下文 JndiObjectFactoryBean/to performing dependency 注入对象对 JMS 目标的引用。

这是我以前从未做过的事情。无论如何,要配置它选择正确的服务器将消息路由到的目标吗?这意味着,如果消息 1 应该传递到服务器 1,那么它甚至不会传递到服务器 2 并保留在队列中,直到服务器 1 使用它?

还有哪些其他方法可以实现这一点?

编辑:

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

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

这里的底线是,您要么需要首先防止重复的消息,要么有某种方法来协调消费者在重复消息被从队列中拉出来后处理重复消息。 我认为您可以使用数据库等外部系统来执行其中任何一个操作,例如:

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

我建议使用"数据库同步后"的替代方案。

保持服务器和侦听器不变,并广播所有+主题上已处理的消息。对于刚刚启动的服务器,您可以使用"持久订阅者"来避免错过任何消息。

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

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

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

最新更新