在AsyncRabbitTemplate

时间:2019-03-06 19:29:17

标签: spring-amqp

使用AsyncRabbitTemplate时,我在处理GZip / GUnzip消息时遇到麻烦。

在这样的同步模板设置下一切正常:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate(final ConnectionFactory connectionFactory) {
    final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
    rabbitTemplate.setMessageConverter(jsonConverter());
    rabbitTemplate.setReplyTimeout(config.getRabbitSendAndReceiveReplyTimeout());
    rabbitTemplate.setReceiveTimeout(config.getRabbitSendAndReceiveReceiveTimeout());
    rabbitTemplate.setAfterReceivePostProcessors(new GUnzipPostProcessor(true));
    rabbitTemplate.setBeforePublishPostProcessors(new GZipPostProcessor(true));
    return rabbitTemplate;
}

但是,当我设置这样的异步模板时:

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public AsyncRabbitTemplate rabbitTemplateAsync(final ConnectionFactory connectionFactory) {
    final AsyncRabbitTemplate asyncRabbitTemplate = new AsyncRabbitTemplate(rabbitTemplate(connectionFactory));
    // need to manually start the reply listener container for some reason
    asyncRabbitTemplate.start();
    return asyncRabbitTemplate;
}

回复消息未正确解压缩,我收到此错误消息

Caused by: java.io.UnsupportedEncodingException: gzip:UTF-8
    at java.lang.StringCoding.decode(Unknown Source) ~[?:1.8.0_192]
    at java.lang.String.<init>(Unknown Source) ~[?:1.8.0_192]
    at java.lang.String.<init>(Unknown Source) ~[?:1.8.0_192]
    at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.convertBytesToObject(AbstractJackson2MessageConverter.java:235) ~[spring-amqp-2.1.4.RELEASE.jar:2.1.4.RELEASE]
    at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.fromMessage(AbstractJackson2MessageConverter.java:199) ~[spring-amqp-2.1.4.RELEASE.jar:2.1.4.RELEASE]
    at org.springframework.amqp.rabbit.AsyncRabbitTemplate.onMessage(AsyncRabbitTemplate.java:576) ~[spring-rabbit-2.1.4.RELEASE.jar:2.1.4.RELEASE]

我尝试为AsyncRabbitTemplate提供配置的DirectReplyToMessageListenerContainer,但这无济于事

    final DirectReplyToMessageListenerContainer directReplyToMessageListenerContainer = new DirectReplyToMessageListenerContainer(
            connectionFactory);
    directReplyToMessageListenerContainer.setAfterReceivePostProcessors(new GUnzipPostProcessor(true));
    final AsyncRabbitTemplate asyncRabbitTemplate = new AsyncRabbitTemplate(rabbitTemplate(connectionFactory),
            directReplyToMessageListenerContainer);

这只会导致此错误:

  

[错误] 2019-03-06 12:18:05.192 [AMQP连接172.17.3.6:5672] CachingConnectionFactory.log-通道关闭:通道错误;协议方法:#method(reply-code = 406,Reply-text = PRECONDITION_FAILED-快速回复使用者不存在,class-id = 60,method-id = 40)

请注意,我可以通过选择spring-rabbit项目的一个分支并将此构造函数添加到AsyncRabbitTemplate中来使事情正常工作

public IndigoAsyncRabbitTemplate(final RabbitTemplate template,
        final DirectReplyToMessageListenerContainer directReplyToContainer) {
    Assert.notNull(template, "'template' cannot be null");
    this.template = template;
    container = null;
    replyAddress = null;
    this.directReplyToContainer = directReplyToContainer;
    directReplyToContainer.setMessageListener(this);
}

那么,这是否会增强Spring Rabbit库的功能?还是有一种方法可以使GUnzip在回复侦听器上工作而不会跳太多圈呢?

1 个答案:

答案 0 :(得分:0)

对,这必须作为框架的改进。对于afterReceivePostProcessors,我们只是缺少AsyncRabbitTemplate的事实。我们可以重新配置内部DirectReplyToMessageListenerContainer,以使用提供的afterReceivePostProcessors中的RabbitTemplate

与此同时,您可以坚持定期进行SimpleMessageListenerContainer注射。 或者,您也可以尝试使用外部DirectReplyToMessageListenerContainer注入。

看到这个故事:

/**
 * Construct an instance using the provided arguments. The first queue the container
 * is configured to listen to will be used as the reply queue. Replies will be
 * routed using the default exchange with that queue name as the routing key.
 * @param template a {@link RabbitTemplate}
 * @param container a {@link AbstractMessageListenerContainer}.
 */
public AsyncRabbitTemplate(RabbitTemplate template, AbstractMessageListenerContainer container) {
    this(template, container, null);
}

此事的问题:https://github.com/spring-projects/spring-amqp/issues/920