【问题标题】:How to have dynamic selector with DefaultMessageListenerContainer (in spring-boot)?如何使用 DefaultMessageListenerContainer 动态选择器(在 spring-boot 中)?
【发布时间】:2016-08-19 15:13:10
【问题描述】:

我有一个带有 ActiveMQ JMS 的 spring-boot 应用程序。我在应用程序中有一个队列,它将获取带有字符串属性的消息,比如颜色。颜色的值可以是红色、绿色或蓝色。应用程序有一个 Rest 服务,它将获取颜色列表 {一个或多个},在侦听队列上的消息时应该将其用作 SELECTOR。在应用程序的整个生命周期中,这可能会发生变化,因此 SELECTOR 的值可能看起来像 "color='red'""color='blue' OR color='red'""color='green'" .

@Bean
MessageListenerAdapter adapter() {        
    return new MessageListenerAdapter(new Object() {
        // message handler
    });
}
@Bean
DefaultMessageListenerContainer container(ConnectionFactory cf) throws Exception {
    DefaultMessageListenerContainer c = new DefaultMessageListenerContainer();
    c.setMessageListener(adapter());
    c.setConcurrency(this.concurrency);
    c.setMessageSelector(this.selector);
    c.setConnectionFactory(cf);
    c.setDestinationName(this.q);

    return c;
}

计划使用上面的代码来实现这一点; code works fine to start with initial selector, however when selector needs to change following code does not work.

c.stop();
// modify value of selector
c.setMessageSelector(this.selector);
c.start();

看起来,我有一个可行的解决方案。我将 @Scope("prototype") 放在方法 container() 之上,并且有一个方法可以在选择器更改时实例化一个新的 DefaultMessageListenerContainer。

public void xx(String selector) {
    this.selector = selector;
    DefaultMessageListenerContainer c = 
        context.getBean("container", DefaultMessageListenerContainer.class);
    c.start();
}

这是解决这个问题的正确方法吗? Also, when selector changes and I instantiate a new DefaultMessageListenerContainer, what's the correct way to shutdown/stop existing DefaultMessageListenerContainer?

问候, 修行者

【问题讨论】:

    标签: spring spring-boot activemq


    【解决方案1】:

    原型对我来说是个很糟糕的主意。

    MessageListenerContainer 是一个单例,负责处理特定队列或主题配置的侦听器。选择器是 JMS 规范,因此您基本上需要在运行时重新配置侦听器容器,这将要求您完全停止侦听器、更改其配置并重新启动它。我没有看到你的代码,但我看不出它不起作用的原因。

    话虽如此,您为什么要为此使用选择器?如果选择器在您的应用程序的生命周期中发生变化,那么在您自己的逻辑中实际执行该选择不是更好吗?如果您在同一个队列上有多个消息类型并且您想要为它们使用不同的线程池(例如,您想要 5 个并发侦听器用于“红色”,而仅 2 个用于绿色),那么在 JMS 级别使用选择器会很有趣。如果您没有这个要求,那么使用过滤传入消息的通用路由可能是一个更好的主意。

    如果您确实有这个要求,停止容器、更改其配置并重新启动它应该可以工作。不幸的是,我创建了SPR-14604 来跟踪这个问题。

    【讨论】:

    • 感谢@stephane-nicoll 的回复。 1> 我已经在bitbucket中创建了一个测试项目,这里是链接bitbucket.org/yovyom/jmsdemoJmsListener类的changeSelector方法更改选择器并没有任何效果。自述文件解释了如何测试/使用应用程序。 2> 关于您对在自己的逻辑中进行选择的评论:想法是基于 SELECTOR 在侦听器之间分配负载。一些侦听器无法处理带有say color='red'的消息,我们不想动态创建队列,每个队列对应一种颜色。
    • 你好@stephane-nicoll,你有机会看看spring-boot项目bitbucket.org/yovyom/jmsdemo
    • 我看了看,确实有一些可疑的地方。我自己在跟踪器上创建了一个问题来调查它。我仍然认为您不应该为此使用选择器。队列中的侦听器 + 代码中的过滤器怎么样? (您可以在自己的代码中获取标头并根据选择器调用一个或另一个 bean ...)。
    • 谢谢@stephane-nicoll。将考虑其他方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2011-07-31
    • 2017-06-29
    • 2019-02-27
    • 2023-02-03
    相关资源
    最近更新 更多