我希望有人为我指明正确的方向以满足某些要求: 我们需要通过我们的服务器发送异步可靠的通知 消息的消费者将随意订阅/取消订阅 消费者数量将会很大 制作人将是其中之一 即使服务器出现故障,通知也不会丢失,如果服务器再次启动,通知也会发送。 预计通知数量会很高 使用的线程数应尽可能少。
考虑到上述(疯狂的)要求,我尝试使用 activemq/jms 来解决这个问题。这看起来是正确的方向吗?
鉴于上述情况: 1.我使用了持久订阅者和jms消息以及kahadb。 2 对于 jms 生产者来说,解决方案似乎很简单。 3.对于消费者端来说,我遇到了麻烦。
a.虽然我有 spring,但我无法使用 jms:listener-container,因为我需要动态订阅和取消订阅消费者,这似乎不可能,所以我为我拥有的每个监听器创建一个 SimpleListenerContainer。这听起来不错吗? b.在 SimpleListenerContainer 中,我设置了 clientId (因为这是持久所需的)
super.setSubscriptionDurable(durable);
if (durable ) super.setClientId(clientId);
在这里,我有以下内容。给定以下配置:
<bean id="messageBusReceiverConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="maxConnections" value="10"/>
<property name="maximumActive" value="500"/>
<property name="connectionFactory" ref="jmsConnectionFactory"/>
<property name="idleTimeout" value="0"/>
</bean>
我预计可能有 10*500=5000 个并行消费者。如果消费者不耐用,情况就是如此。但是,对于持久消费者,使用 super.setClientId(clientId) (super 是 SimpleMessageListenerContainer),在第 10 个连接后,我得到: org.springframework.jms.IllegalStateException:不允许在已使用的连接上设置clientID;嵌套异常是 javax.jms.IllegalStateException:不允许在已使用的连接上设置 clientID
所以看来我不能使用 SimpleMessageListenerContainer 的持久订阅者进行 session ,而只能用于连接。这是真的? maxConnections=500 和 MaximumActive=1 听起来合理吗?这解决了我的问题,但是...虽然对 JMS 来说是新的,但这对于代理来说似乎有点矫枉过正。
好吧,考虑到我仍然处于正确的轨道上,我现在需要动态地取消订阅我的消费者/听众,所以我这样做
container.stop();
container.destroy();
其中容器是 SimpleMessageListenerContainer。容器.destroy();调用时抛出一些异常。是否有必要调用它或停止方法就足够了?
好吧,我知道这些问题是任意的,即使对于了解 jms 的人(如果 jms 是正确的解决方案)并且从我的代码中几乎没有给出任何内容,也可能很难回答。我希望有人给我一些指导,告诉我我是否走在正确的轨道上,就提出的问题尽可能多地向我提供意见,然后我可以在需要的地方给出代码,以解决我剩下的问题。
最佳答案
我缺乏有关 spring 的知识来回答您有关 IllegalStateException 的问题,尽管我猜测它与 maxConnections 设置为 10 有关。
你需要 Spring 吗?无论如何,请确保您在 JMS Broker 的配置中启用了持久性,确保使用持久队列/主题,并确保对消息使用 setDurable(true)
。
我认为,如果您想要可靠的消息传递,那么使用强大的 JMS 提供程序通常是正确的决定。您可以使用SPECjms2007基准测试各种产品,具体取决于性能对您的重要程度,还有一些results可用。
关于java - JMS持久异步事件通知,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13480140/