java—rabbittemplate的waitforconfirms和阻塞相关数据回调之间的性能差异

ttp71kqs  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(501)

我正在实现一个服务,该服务需要以可靠和阻塞的方式将消息发布到rabbitmq代理。如中所述https://www.rabbitmq.com/tutorials/tutorial-seven-java.html,有多个用于确认发布者的选项。最基本的选择是使用 waitForConfirms . 我测试了以下代码(使用设置 cachingConnectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.SIMPLE) )发布10000条信息花了大约100秒:

rabbitTemplate.invoke(rabbitOperations -> {
  rabbitOperations.convertAndSend("test_exchange", "test_key", "test message");
  return rabbitOperations.waitForConfirms(1000);
});

我还测试了异步选项(设置为 cachingConnectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED) )用一个非常原始的阻塞 Package 器。以下代码花费了大约20秒来发布10000条消息:

CountDownLatch latch = new CountDownLatch(1);
CorrelationData correlationData = new CorrelationData();
rabbitTemplate.convertAndSend("test_exchange", "test_key", "test message", correlationData);
correlationData.getFuture().addCallback(success -> {
  latch.countDown();
}, failure -> {
  latch.countDown();
});
latch.await();

就我所理解的上面链接中的以下引用而言,我的第一个示例应该与我的第二个示例基本相同。
把waitforconfirmsodie看作一个同步的助手,它依赖于后台的异步通知。
但性能差异太大,我的假设不成立。我看到了 RabbitTemplate.invoke 执行的东西比我的第二个代码示例多得多。但这种巨大的性能差异究竟是什么原因呢?我的第二个例子是不好的做法,还是我的第一个例子在某些不必要的方面效率低下?
编辑复制粘贴gary的代码,我经历了以下几点:

StopWatch '': running time = 106379462700 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
17546479900  016 %  correlated
88832982800  084 %  simple

我使用的是windows10pro,rabbitmq3.8.9,通过 docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management ,和Spring Boot2.3.1
编辑2添加 RabbitUtils.isPhysicalCloseRequired() 加里的简单确认码:

simpleTemplate.invoke(ops -> {
  ops.convertAndSend("so64857773", "test message");
  RabbitUtils.isPhysicalCloseRequired();
  return ops.waitForConfirms(1000);
});

产生以下结果:

StopWatch '': running time = 46090067400 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
21100935900  046 %  correlated
24989131500  054 %  simple

似乎在windows上运行rabbitmq的停靠版本时,关闭和重新创建一个通道是相当昂贵的。
edit3使用原生windows10rabbitmq服务器(3.8.9)和erlang23.1.3,性能大大提高。使用10k消息,相关确认测试只花了大约3秒钟。我将下面两个测试的消息数增加到50k。
第一个测试,使用gary的原始代码:

StopWatch '': running time = 144403128200 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
19750222900  014 %  correlated
124652905300  086 %  simple

第二次试验 RabbitUtils.isPhysicalCloseRequired() 如编辑2中所述添加:

StopWatch '': running time = 30030523500 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
14549132300  048 %  correlated
15481391200  052 %  simple

关闭和重新打开一个频道似乎是非常昂贵的windows-这似乎不是一个问题,使用停靠版本。

e1xvtsh3

e1xvtsh31#

有更多的代码涉及到相关的确认,所以我本以为该版本需要更多的时间(虽然没有很大的区别)。
我不知道你为什么看到你观察到的行为。
但是,在这两种情况下,最好在等待确认之前发送多个请求;发送和等待每一个都会慢得多。
使用关联确认,您可以保存 CorrelationData 示例,然后等待未来。
编辑
我看不到和你一样的行为;我使用这两种方法得到几乎相同的性能;每次大约62秒。

@SpringBootApplication
public class So64857773Application {

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

//  @Bean
//  Queue queue() {
//      return new Queue("so64857773");
//  }

    @Bean
    ApplicationRunner runner(CachingConnectionFactory cf, RabbitTemplate template) {
        return args -> {
            StopWatch watch = new StopWatch();
            cf.createConnection().close();
            watch.start("correlated");
            for (int i = 0; i < 10_000; i++) {
                CorrelationData cd = new CorrelationData();
                template.convertAndSend("", "so64857773", "test message", cd);
                cd.getFuture().get(1, TimeUnit.SECONDS);
            };
            watch.stop();

            cf.resetConnection();
            cf.setPublisherConfirmType(ConfirmType.SIMPLE);
            RabbitTemplate simpleTemplate = new RabbitTemplate(cf);
            cf.createConnection().close();
            watch.start("simple");
            for (int i = 0; i < 10_000; i++) {
                simpleTemplate.invoke(ops -> {
                    ops.convertAndSend("so64857773", "test message");
                    return ops.waitForConfirms(1000);
                });
            };
            watch.stop();

            System.out.println(watch.prettyPrint());
        };
    }

}
spring.rabbitmq.publisher-confirm-type=correlated

结果:

StopWatch '': running time = 124245233864 ns
---------------------------------------------
ns         %     Task name
---------------------------------------------
62136894432  050%  correlated
62108339432  050%  simple

相关问题