Spring AMQP - 频道交易与发布商确认

时间:2018-01-04 11:55:26

标签: java spring amqp spring-amqp

我有一个Jersey应用程序,我在其中使用spring amqp库向rabbitMQ交换发布消息。我在我的兔子模板中使用CachingConnectionFactory,最初将Channel-Transacted设置为false。我注意到有些消息实际上没有发布到交换机,因此我将频道交易值更改为true。

在执行此操作时,我的发布功能开始花费500毫秒(当通道交易为假时为5毫秒)。我在这里缺少什么,因为500毫秒太多了。

作为替代方案,我尝试将publisherConfirms设置为true并添加了ConfirmCallback。我还没有对此进行基准测试,但是想知道这与通道交易相比是否会有更好的性能,因为此应用程序的唯一目的是在RabbitMQ中向交换发布消息?

另外,如果我选择publisherConfirms,我想在失败的情况下实现重试,或者至少能够抛出异常。通过频道交易,我会在出现故障时获得异常,但在这种情况下延迟很高。我不确定如何使用publisherConfirms实现重试。

我尝试重试发布商确认,但我的代码只是挂起。

这是我的代码:

CompleteMessageCorrelationData.java

public class CompleteMessageCorrelationData extends CorrelationData {

    private final Message message;
    private final int retryCount;

    public CompleteMessageCorrelationData(String id, Message message, int retryCount) {
        super(id);
        this.message = message;
        this.retryCount = retryCount;
    }

    public Message getMessage() {
        return this.message;
    }

    public int getRetryCount() {
        return this.retryCount;
    }

    @Override
    public String toString() {
        return "CompleteMessageCorrelationData [id=" + getId() + ", message=" + this.message + "]";
    }

}

设置CachingConnectionFactory:

private static CachingConnectionFactory factory = new CachingConnectionFactory("host");
static {
    factory.setUsername("rmq-user");
    factory.setPassword("rmq-password");
    factory.setChannelCacheSize(50);
    factory.setPublisherConfirms(true);
}
private final RabbitTemplate rabbitTemplate = new RabbitTemplate(factory);
rabbitTemplate.setConfirmCallback((correlation, ack, reason) -> {
        if (correlation != null && !ack) {
            CompleteMessageCorrelationData data = (CompleteMessageCorrelationData)correlation;
            log.info("Received nack for message: " + data.getMessage() + " for reason : " + reason);
            int counter = data.getRetryCount();
            if (counter < Integer.parseInt(max_retries)){
                this.rabbitTemplate.convertAndSend(data.getMessage().getMessageProperties().getReceivedExchange(),
                        data.getMessage().getMessageProperties().getReceivedRoutingKey(),
                        data.getMessage(), new CompleteMessageCorrelationData(id, data.getMessage(), counter++));
            } else {
                log.error("Max retries exceeded for message: " + data.getMessage());
            }
        }
    });

发布消息:

rabbitTemplate.convertAndSend(exchangeName, routingKey, message, new CompleteMessageCorrelationData(id, message, 0));

简而言之:

  1. 渠道交易我做错了,延迟是如此之高?

  2. 如果我要实施publisherConfirms,除了重试之外,我的方法有什么问题,并且它会比通道交易更好,考虑到除了向rabbitmq发布消息之外没有其他工作吗?

1 个答案:

答案 0 :(得分:0)

正如您所发现的,交易成本高昂且性能显着下降;然而,500毫秒似乎很高。

我不相信出版商确认会有所帮助。在释放servlet线程之前,您仍然需要等待到代理的往返。当您发送大量消息然后等待所有确认返回时,发布者确认很有用;但是当你只发送一条消息然后等待确认时,它可能不会比使用交易快得多。

你可以尝试一下,但是代码有点复杂,特别是如果你想处理异常,你得到的是免费的&#34;与交易。