Spring integration 带轮询器的Spring集成桥未按预期用于JMS

Spring integration 带轮询器的Spring集成桥未按预期用于JMS,spring-integration,Spring Integration,使用SpringIntegration5.0.7来限制两个JMS队列之间MSG的桥接 文档位于: 建议: <int:bridge input-channel="pollable" output-channel="subscribable"> <int:poller max-messages-per-poll="10" fixed-rate="5000"/> </int:bridge> 这是一个SpringBoot应用程序,使用JavaDSL配置,

使用SpringIntegration5.0.7来限制两个JMS队列之间MSG的桥接

文档位于:

建议:

<int:bridge input-channel="pollable" output-channel="subscribable">
     <int:poller max-messages-per-poll="10" fixed-rate="5000"/>
 </int:bridge>

这是一个SpringBoot应用程序,使用JavaDSL配置,与XML中的配置完全相同(不包括桥接);它很好用

@SpringBootApplication
public class So51792909Application {

    private static final Logger logger = LoggerFactory.getLogger(So51792909Application.class);

    public static void main(String[] args) {
        SpringApplication.run(So51792909Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(JmsTemplate template) {
        return args -> {
            for (int i = 0; i < 10; i++) {
                template.convertAndSend("foo", "test");
            }
        };
    }

    @Bean
    public IntegrationFlow flow(ConnectionFactory connectionFactory) {
        return IntegrationFlows.from(Jms.inboundAdapter(connectionFactory)
                        .destination("foo"), e -> e
                            .poller(Pollers
                                    .fixedDelay(5000)
                                    .maxMessagesPerPoll(2)))
                .handle(Jms.outboundAdapter(connectionFactory)
                        .destination("bar"))
                .get();
    }

    @JmsListener(destination = "bar")
    public void listen(String in) {
        logger.info(in);
    }

}
如您所见,消费者每5秒收到2条消息

调试日志表明队列中没有消息

编辑

我明白了;XML解析器将JmsTemplate receiveTimeout设置为nowait(-1)。因为您没有使用缓存连接工厂,所以我们永远不会收到消息,因为如果客户端()中还没有消息,ActiveMQ客户端将立即返回。由于没有缓存,我们在每次轮询中都会得到一个新的消费者(并且每次都进行无等待接收)

DSL保留JmsTemplate的默认值(无限等待-这实际上是错误的,因为如果没有消息,它会无限期地阻塞轮询器线程)

要修复XML版本,请添加
receive timeout=“1000”
修复它

但是,最好使用
CachingConnectionFactory
,以避免在每次轮询时创建新的连接/会话/使用者

不幸的是,配置
CachingConnectionFactory
会关闭Spring Boot的自动配置。这是

我提出了一个问题来解决DSL和XML之间的不一致性

如果您坚持使用DSL,我建议将接收超时设置为合理的值,而不是不确定的值:

@Bean
public IntegrationFlow flow(ConnectionFactory connectionFactory) {
    return IntegrationFlows.from(Jms.inboundAdapter(connectionFactory)
                    .configureJmsTemplate(t -> t.receiveTimeout(1000))
                    .destination("foo"), e -> e
                        .poller(Pollers
                                .fixedDelay(5000)
                                .maxMessagesPerPoll(2)))
            .handle(Jms.outboundAdapter(connectionFactory)
                    .destination("bar"))
            .get();
}

但是,最好的解决方案是使用
CachingConnectionFactory

您不需要桥接器,只需使用一个通道即可。也就是说,它应该可以正常工作。打开调试日志以查看它是否能提供任何线索。我想如果我想在spring集成中处理msg,是的,我不需要桥接到另一个队列……但现在我想保留当前的使用者。在上面的代码中,您只需将入站适配器的通道桥接到出站适配器的通道。这是不必要的;两个适配器可以使用相同的通道;入站适配器的轮询器将直接将消息发送到出站适配器。好的,尝试使用一个通道。没什么区别。我们是否确定使用JmsConnectionFactory在入站通道适配器上支持轮询?如果我使用直接的消息驱动通道适配器,它工作得很好,但当然没有节流;这座桥根本不需要。正如我还说过的,调试日志将向您显示消息传递活动。您是否使用嵌入式ActiveMQ代理进行测试?如果是这样,您可能需要使用
CachingConnectionFactory
来避免代理在删除测试消息和轮询之间停止/启动,这可能会导致队列消失。在我的示例中,连接由侦听器保持打开状态。不,它是一个独立的代理,AMQ控制台坚持队列中有东西。如果我将xml流从入站通道适配器更改为消息驱动通道适配器(不带轮询器),它将很好地接收它们。同时,JavaDSL示例可以完美地工作,因此我们将使用这种方法。
@SpringBootApplication
public class So51792909Application {

    private static final Logger logger = LoggerFactory.getLogger(So51792909Application.class);

    public static void main(String[] args) {
        SpringApplication.run(So51792909Application.class, args);
    }

    @Bean
    public ApplicationRunner runner(JmsTemplate template) {
        return args -> {
            for (int i = 0; i < 10; i++) {
                template.convertAndSend("foo", "test");
            }
        };
    }

    @Bean
    public IntegrationFlow flow(ConnectionFactory connectionFactory) {
        return IntegrationFlows.from(Jms.inboundAdapter(connectionFactory)
                        .destination("foo"), e -> e
                            .poller(Pollers
                                    .fixedDelay(5000)
                                    .maxMessagesPerPoll(2)))
                .handle(Jms.outboundAdapter(connectionFactory)
                        .destination("bar"))
                .get();
    }

    @JmsListener(destination = "bar")
    public void listen(String in) {
        logger.info(in);
    }

}
2018-08-10 19:38:52.534  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:38:52.543  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:38:57.566  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:38:57.582  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:39:02.608  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:39:02.622  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:39:07.640  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:39:07.653  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:39:12.672  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
2018-08-10 19:39:12.687  INFO 13408 --- [enerContainer-1] com.example.So51792909Application        : test
@Bean
public IntegrationFlow flow(ConnectionFactory connectionFactory) {
    return IntegrationFlows.from(Jms.inboundAdapter(connectionFactory)
                    .configureJmsTemplate(t -> t.receiveTimeout(1000))
                    .destination("foo"), e -> e
                        .poller(Pollers
                                .fixedDelay(5000)
                                .maxMessagesPerPoll(2)))
            .handle(Jms.outboundAdapter(connectionFactory)
                    .destination("bar"))
            .get();
}