使用侦听器设置CMS消费者涉及两个单独的调用:首先,获取消费者:
cms::MessageConsumer* cms::Session::createConsumer( const cms::Destination* );
然后,在消费者上设置一个监听器:
void cms::MessageConsumer::setMessageListener( cms::MessageListener* );
如果实现在侦听器被激活之前订阅了目标(并从代理/路由器接收消息(,那么消息会丢失吗?或者这些消息是在内部排队并在激活时传递给侦听器?
为什么没有API调用来创建以侦听器作为构造参数的消费者?(是因为JMS规范没有它吗?(
(补充:这可能是API本身的缺陷。更合乎逻辑的顺序是从会话中实例化消费者,并在API中使用cms::Consumer::subscribe( cms::Destination*, cms::MessageListener* )
方法。(
我认为API不一定有缺陷。显然,它可以用不同的方式设计,但我相信您所声称的问题的解决方案来自Connection
对象上的start
方法(通过Startable
继承(。Connection
的文档说明:
CMS客户端通常会创建一个连接、一个或多个会话以及多个消息生产者和消费者。创建连接时,它处于停止模式。这意味着没有传递任何消息。
通常将连接保持在停止模式,直到安装完成(即,直到创建了所有消息使用者(。这时,客户端调用连接的start方法,消息开始到达连接的使用者。当客户端仍在进行自身设置时,此设置约定最大限度地减少了异步消息传递可能导致的客户端混乱。
可以立即启动连接,然后再进行设置。执行此操作的客户端必须准备好在设置过程中处理异步消息传递。
这与JMS遵循的模式相同。
在任何情况下,我认为无论何时调用start()
都不会有消息丢失的风险。如果使用者使用的是自动确认模式,那么只有在消息通过其中一个接收方法同步传递或通过侦听器的onMessage
异步传递后,才应自动确认消息。否则的话,我估计是个错误。在过去的10年里,我与JMS合作了各种实现,从未见过任何与此相关的消息丢失情况。
如果您想在调用start()
之后添加消费者,您当然可以先调用stop()
,但我认为简单地动态添加消费者没有任何问题。