带有轮询器的Spring Integration Bridge无法按预期的方式运行JMS

时间:2018-08-10 19:23:07

标签: spring-integration

使用spring-integration 5.0.7限制两个JMS队列之间的msg桥接。

位于https://docs.spring.io/spring-integration/docs/5.0.7.RELEASE/reference/html/messaging-channels-section.html#bridge-namespace

的文档

建议:

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

但是架构验证器抱怨“桥elt上的“可嵌套输入通道不允许嵌套轮询器”。

但是,如果我将轮询器放在输入通道适配器上,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:int="http://www.springframework.org/schema/integration"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:beans="http://www.springframework.org/schema/beans"
             xmlns:int-jms="http://www.springframework.org/schema/integration/jms"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/integration
            http://www.springframework.org/schema/integration/spring-integration.xsd
            http://www.springframework.org/schema/integration/jms
            http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd
 ">
    <int:channel id="inChannel" />
    <int:channel id="outChannel" />

    <int-jms:inbound-channel-adapter id="jmsIn" connection-factory="jmsConnectionFactory" destination-name="_dev.inQueue" channel="inChannel">
       <int:poller fixed-delay="5000" max-messages-per-poll="2"/>
    </int-jms:inbound-channel-adapter>

    <int-jms:outbound-channel-adapter id="jmsOut" connection-factory="jmsConnectionFactory" destination-name="_dev.outQueue" channel="outChannel"/>
    <int:bridge input-channel="inChannel" output-channel="outChannel">
    </int:bridge>
</beans:beans>

什么都不会从输入移到输出。

如何通过速率限制从一个JMS队列桥接到另一个?

更新:

打开日志记录可确认没有任何东西从输入通道中拾取,但无济于事:

018-08-10 15:36:33.345 DEBUG 112066 --- [ask-scheduler-1] o.s.i.e.SourcePollingChannelAdapter      : Received no Message during the poll, returning 'false'
2018-08-10 15:36:38.113 DEBUG 112066 --- [ask-scheduler-2] o.s.integration.jms.DynamicJmsTemplate   : Executing callback on JMS Session: ActiveMQSession {id=ID:whitechapel-35247-1533940593148-3:2:1,started=true} java.lang.Object@5c278302
2018-08-10 15:36:38.116 DEBUG 112066 --- [ask-scheduler-2] o.s.i.e.SourcePollingChannelAdapter      : Received no Message during the poll, returning 'false'
2018-08-10 15:36:43.115 DEBUG 112066 --- [ask-scheduler-1] o.s.integration.jms.DynamicJmsTemplate   : Executing callback on JMS Session: ActiveMQSession {id=ID:whitechapel-35247-1533940593148-3:3:1,started=true} java.lang.Object@1c09a81e
2018-08-10 15:36:43.118 DEBUG 112066 --- [ask-scheduler-1] o.s.i.e.SourcePollingChannelAdapter      : Received no Message during the poll, returning 'false'

1 个答案:

答案 0 :(得分:1)

这里是一个Spring Boot应用程序,它使用Java DSL配置,与您在XML中的功能完全相同(减去网桥);效果很好。

DetailsActivity.mContactDatabase.contactDao().addTimestamp(contact_number,datastamp);
DetailsActivity.mContactDatabase.contactDao().delCredit(contact_number,del_credit);

@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)。由于您没有使用缓存连接工厂,因此我们永远不会收到消息,因为如果客户端中没有消息(see this answer,则ActiveMQ客户端会立即返回。由于没有缓存,因此每次轮询都会吸引一个新用户(并且每次都无需等待)。

DSL保留了JmsTemplate的默认设置(无限等待-这实际上是错误的,因为如果没有消息,它将无限期地阻止轮询线程)。

要修复XML版本,请添加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 来对其进行修复。

但是,最好使用receive-timeout="1000"以避免在每次轮询中创建新的连接/会话/消费者。

不幸的是,配置CachingConnectionFactory关闭了Spring Boot的自动配置。这是fixed in Boot 2.1

我已经解决了DSL与XML here之间的不一致问题。

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

CachingConnectionFactory

但是,最好的解决方案是使用@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(); }