RabbitMQ 基础

目录

一.核心概念

1.Producer和Consumer

2.Connection和Channel

[3.Virtual host](#3.Virtual host)

4.Queue

5.Exchange

二.工作模式

1.Simple(简单模式)

[2.Work Queue(工作队列)](#2.Work Queue(工作队列))

3.Publish/Subscribe(发布/订阅模式)

4.Routing(路由模式)

5.Topics(通配符模式)

6.RPC(RPC通信)

[7.Publisher Confirms(发布确认)](#7.Publisher Confirms(发布确认))

一.核心概念

1.Producer和Consumer

Producer:生产者,是RabbitMQ Server的客户端,向RabbitMQ发送消息;

Consumer:消费者,是RabbitMQ Server的客户端,从RabbitMQ接收消息;

Broker:是RabbitMQ Server,主要是接收和收发消息;

2.Connection和Channel

Connection:连接,是客户端和RabbitMQ服务器之间的⼀个TCP连接。这个连接是建立消息传递的基础, 它负责传输客户端和服务器之间的所有数据和控制信息;

Channel:信道, Channel是在Connection之上的⼀个抽象层。在 RabbitMQ 中,⼀个TCP连接可以有多个Channel,每个Channel 都是独立的虚拟连接。消息的发送和接收都是基于 Channel的。通道的主要作用是将消息的读写操作复用到同⼀个TCP连接上,这样可以减少建立和关闭连接的开销,提高性能。

3.Virtual host

虚拟主机。这是⼀个虚拟概念。它为消息队列提供了⼀种逻辑上的隔离机制。对于RabbitMQ而言,⼀个 BrokerServer 上可以存在多个 Virtual Host。当多个不同的用户使用同⼀个RabbitMQ Server 提供的服务时,可以虚拟划分出多个 vhost,每个用户在自己的 vhost 创建exchange/queue 等

4.Queue

队列,是RabbitMQ的内部对象,用于存储消息

5.Exchange

交换机。生产者将消息发送到Exchange,由交换机将消息按⼀定规则路由到⼀个或多个队列中。交换机只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息就会丢失。

RabbitMQ交换机有四种类型:Fanout、Direct、topic、Headers,不同类型有着不同的路由策略。

1)Fanout:广播,将消息交给所有绑定到交换机的队列;

2)Direct:定向,把消息交给符合指定routing key的队列;

3)Topic:通配符,把消息交给符合routing pattern(路由模式)的队列;

4)Headers:交换器不依赖于路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。Headers类型的交换器性能会很差,而且也不使用,基本上不会看到它的存在。

RoutingKey:路由键。生产者将消息发给交换器时,指定的⼀个字符串,用来告诉交换机应该如何处理这个消息;

Binding Key:绑定。RabbitMQ中通过Binding(绑定)将交换器与队列关联起来,在绑定的时候⼀般会指定⼀个Binding Key,这样RabbitMQ就知道如何正确地将消息路由到队列了。

二.工作模式

一共有7中工作模式,想了解更多请看官网:RabbitMQ Tutorials | RabbitMQ

1.Simple(简单模式)

P:生产者,发送消息的程序

C:消费者,消费的接收者

Queue:消息队列,生产者可以向其发送信息,消费者可以从中取出消息

Producer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机
//4.声明队列
channel.queueDeclare("hello",true,false,false,null);
//5.发送消息
String msg="hello rabbitmq";
channel.basicPublish("","hello",null,msg.getBytes());
//6.释放连接
channel.close();
connection.close();

Consumer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机
//4.声明队列
channel.queueDeclare("hello",true,false,false,null);
//5.消费消息
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        System.out.println("接收到消息:"+new String(body));
    }
};
channel.basicConsume("hello",true,consumer);
//6.释放连接
channel.close();
connection.close();

2.Work Queue(工作队列)

一个生产者P,多个消费者C1、C2,Queue将信息分给不同消费者,消息不会重复,分配给不同的消费者。适用于集群环境中做异步处理。

Producer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机,声明队列
channel.queueDeclare(Constants.WORK_QUEUE,true,false,false,null);
//4.发送消息
String msg="hello work queue";
channel.basicPublish("",Constants.WORK_QUEUE,null,msg.getBytes());
//5.释放连接
channel.close();
connection.close();

Consumer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机,声明队列
channel.queueDeclare(Constants.WORK_QUEUE,true,false,false,null);
//4.消费消息
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        System.out.println("接收到消息:"+new String(body));
    }
};
channel.basicConsume(Constants.WORK_QUEUE,true,consumer);
//5.释放连接
channel.close();
connection.close();

3.Publish/Subscribe(发布/订阅模式)

X:交换机,是Fanout类型的

交换机将消息复制多份,每个消费者C都接收相同的消息。适用于消息需要被多个消费者同时接收的场景。

Producer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机
channel.exchangeDeclare(Constants.FANOUT_EXCHANGE, BuiltinExchangeType.FANOUT,true);
//4.声明队列
channel.queueDeclare(Constants.FANOUT_QUEUE1,true,false,false,null);
channel.queueDeclare(Constants.FANOUT_QUEUE2,true,false,false,null);
//5.绑定交换机和队列
channel.queueBind(Constants.FANOUT_QUEUE1,Constants.FANOUT_EXCHANGE,"");
channel.queueBind(Constants.FANOUT_QUEUE2,Constants.FANOUT_EXCHANGE,"");
//6.发布消息
String msg="hello fanout";
channel.basicPublish(Constants.FANOUT_EXCHANGE,"",null,msg.getBytes());
//7.释放连接
channel.close();
connection.close();

Consumer:

java 复制代码
// 有两个消费者,这里只给出一个
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明队列
channel.queueDeclare(Constants.FANOUT_QUEUE1,true,false,false,null);
//5.消费消息
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        System.out.println("接收到消息:"+new String(body));
    }
};
channel.basicConsume(Constants.FANOUT_QUEUE1,true,consumer);
//6.释放连接
channel.close();
connection.close();

4.Routing(路由模式)

X:交换机,是Direct类型的

交换机根据RoutingKey分发给对应的消费者队列,就如上图的abc。适用于需要特定规则分发消息的场景。

Producer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机
channel.exchangeDeclare(Constants.DIRECT_EXCHANGE, BuiltinExchangeType.DIRECT,true);
//4.声明队列
channel.queueDeclare(Constants.DIRECT_QUEUE1,true,false,false,null);
channel.queueDeclare(Constants.DIRECT_QUEUE2,true,false,false,null);
//5.绑定交换机和队列
channel.queueBind(Constants.DIRECT_QUEUE1,Constants.DIRECT_EXCHANGE,"a");
channel.queueBind(Constants.DIRECT_QUEUE2,Constants.DIRECT_EXCHANGE,"a");
channel.queueBind(Constants.DIRECT_QUEUE2,Constants.DIRECT_EXCHANGE,"b");
channel.queueBind(Constants.DIRECT_QUEUE2,Constants.DIRECT_EXCHANGE,"c");
//6.发布消息
String msg_a="hello routingKey is a";
channel.basicPublish(Constants.DIRECT_EXCHANGE,"a",null,msg_a.getBytes());
String msg_b="hello routingKey is b";
channel.basicPublish(Constants.DIRECT_EXCHANGE,"b",null,msg_b.getBytes());
String msg_c="hello routingKey is c";
channel.basicPublish(Constants.DIRECT_EXCHANGE,"c",null,msg_c.getBytes());
//7.释放连接
channel.close();
connection.close();

Consumer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明队列
channel.queueDeclare(Constants.DIRECT_QUEUE1,true,false,false,null);
//5.消费消息
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        System.out.println("接收到消息:"+new String(body));
    }
};
channel.basicConsume(Constants.DIRECT_QUEUE1,true,consumer);
//6.释放连接
channel.close();
connection.close();

5.Topics(通配符模式)

路由模式的升级版,路由的RoutingKey可以通过正则表达式的方式来定义,匹配更加灵活。

Producer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明交换机
channel.exchangeDeclare(Constants.TOPIC_EXCHANGE, BuiltinExchangeType.TOPIC,true);
//4.声明队列
channel.queueDeclare(Constants.TOPIC_QUEUE1,true,false,false,null);
channel.queueDeclare(Constants.TOPIC_QUEUE2,true,false,false,null);
//5.绑定交换机和队列
channel.queueBind(Constants.TOPIC_QUEUE1,Constants.TOPIC_EXCHANGE,"*.a.*");
channel.queueBind(Constants.TOPIC_QUEUE2,Constants.TOPIC_EXCHANGE,"*.*.b");
channel.queueBind(Constants.TOPIC_QUEUE2,Constants.TOPIC_EXCHANGE,"c.#");
//6.发布消息
String msg_a="hello topic,routingKey is r.a.few";
channel.basicPublish(Constants.TOPIC_EXCHANGE,"er.a.few",null,msg_a.getBytes());
String msg_b="hello topic,routingKey is erg.a.b";
channel.basicPublish(Constants.TOPIC_EXCHANGE,"erg.a.b",null,msg_b.getBytes());
String msg_c="hello topic,routingKey is c";
channel.basicPublish(Constants.TOPIC_EXCHANGE,"c.wfew",null,msg_c.getBytes());
//7.释放连接
channel.close();
connection.close();

​​​​​​​Consumer:

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明队列
channel.queueDeclare(Constants.TOPIC_QUEUE1,true,false,false,null);
//5.消费消息
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        System.out.println("接收到消息:"+new String(body));
    }
};
channel.basicConsume(Constants.TOPIC_QUEUE1,true,consumer);
//6.释放连接
channel.close();
connection.close();

6.RPC(RPC通信)

在RPC通信中,没有消费者和生产者,通过两个队列来实现一个可回调的过程。

1)客户端发送消息到⼀个指定的队列,并在消息属性中设置replyTo字段,这个字段指定了⼀个回调队列, 用于接收服务端的响应;

2)服务端接收到请求后,处理请求并发送响应消息到replyTo指定的回调队列;

3)客户端在回调队列上等待响应消息。⼀旦收到响应,客户端会检查消息的correlationId属性,以确保它是所期望的响应。

Client(客户端):

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.声明队列
channel.queueDeclare(Constants.RPC_REQUEST_QUEUE,true,false,false,null);
channel.queueDeclare(Constants.RPC_RESPONSE_QUEUE,true,false,false,null);
//4.发送请求
//消息内容
String msg="hello rpc";
//设置请求的唯一标识
String correlationId= UUID.randomUUID().toString();
//设置相关属性
AMQP.BasicProperties pros=new AMQP.BasicProperties().builder()
        .correlationId(correlationId)
        .replyTo(Constants.RPC_RESPONSE_QUEUE)
        .build();
channel.basicPublish("",Constants.RPC_REQUEST_QUEUE,pros,msg.getBytes());
//5.接收响应
final BlockingQueue<String> response=new ArrayBlockingQueue<>(1);
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        String respMsg=new String(body);
        System.out.println("接收到消息");
        if(correlationId.equals(properties.getCorrelationId())){
            response.offer(respMsg);
        }
    }
};
channel.basicConsume(Constants.RPC_RESPONSE_QUEUE,true,consumer);
String result=response.take();
System.out.println("rpc接收到的信息是:"+result);

​​​​​​​Server(服务端):

java 复制代码
//1.创建连接
ConnectionFactory connectionFactory=new ConnectionFactory();
connectionFactory.setHost(Constants.HOST);
connectionFactory.setPort(Constants.PORT);
connectionFactory.setUsername(Constants.USER_NAME);
connectionFactory.setPassword(Constants.PASSWORD);
connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
Connection connection=connectionFactory.newConnection();
//2.开启信道
Channel channel=connection.createChannel();
//3.接收请求
channel.basicQos(1);    //设置每次只能有一个请求
DefaultConsumer consumer=new DefaultConsumer(channel){
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        String request=new String(body,"UTF-8");
        System.out.println("接收到请求消息");
        String response="针对请求:"+request+",请求成功";
        AMQP.BasicProperties pros=new AMQP.BasicProperties().builder()
                .correlationId(properties.getCorrelationId())
                .build();
        channel.basicPublish("",Constants.RPC_RESPONSE_QUEUE,pros,response.getBytes());
        channel.basicAck(envelope.getDeliveryTag(),false);
    }
};
channel.basicConsume(Constants.RPC_REQUEST_QUEUE,false,consumer);

7.Publisher Confirms(发布确认)

Publisher Confirms模式是RabbitMQ提供的⼀种确保消息可靠发送到RabbitMQ服务器的机制。在这种模式下,生产者可以等待RabbitMQ服务器的确认,以确保消息已经被服务器接收并处理。通过Publisher Confirms模式,生产者可以确保消息被RabbitMQ服务器成功接收, 从而避免消息丢失

的问题。

具体过程:

1)生产者将Channel设置为confirm模式(通过调用channel.confirmSelect()完成)后, 发布的每一条消息都会获得⼀个唯⼀的ID,生产者可以将这些序列号与消息关联起来,以便跟踪消息的状态;

2)当消息被RabbitMQ服务器接收并处理后,服务器会异步地向生产者发送⼀个确认(ACK)给生产者(包含消息的唯⼀ID),表明消息已经送达。

java 复制代码
public class PublisherConfirms {
    private static final Integer MESSAGE_COUNT = 10000;
    static Connection createConnection() throws Exception {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT); //需要提前开放端口号
        connectionFactory.setUsername(Constants.USER_NAME);//账号
        connectionFactory.setPassword(Constants.PASSWORD);  //密码
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST); //虚拟主机
        return connectionFactory.newConnection();
    }


    public static void main(String[] args) throws Exception {
        //单独确认
        publishingMessagesIndividually();
        //批量确认
        publishingMessagesInBatches();
        //异步确认
        //handlingPublisherConfirmsAsynchronously();
    }

    /**
     * 异步确认
     */
    private static void handlingPublisherConfirmsAsynchronously() throws Exception{
        try (Connection connection = createConnection()){
            //1. 开启信道
            Channel channel = connection.createChannel();
            //2. 设置信道为confirm模式
            channel.confirmSelect();
            //3. 声明队列
            channel.queueDeclare(Constants.PUBLISHER_CONFIRMS_QUEUE3, true, false, false, null);
            //4. 监听confirm
            //集合中存储的是未确认的消息ID
            long start = System.currentTimeMillis();
            SortedSet<Long> confirmSeqNo = Collections.synchronizedSortedSet(new TreeSet<>());

            channel.addConfirmListener(new ConfirmListener() {
                @Override
                public void handleAck(long deliveryTag, boolean multiple) throws IOException {
                    if (multiple){
                        confirmSeqNo.headSet(deliveryTag+1).clear();
                    }else {
                        confirmSeqNo.remove(deliveryTag);
                    }
                }

                @Override
                public void handleNack(long deliveryTag, boolean multiple) throws IOException {
                    if (multiple){
                        confirmSeqNo.headSet(deliveryTag+1).clear();
                    }else {
                        confirmSeqNo.remove(deliveryTag);
                    }
                    //业务需要根据实际场景进行处理, 比如重发, 此处代码省略
                }
            });
            //5. 发送消息
            for (int i = 0; i < MESSAGE_COUNT; i++) {
                String msg = "hello publisher confirms"+i;
                long seqNo = channel.getNextPublishSeqNo();
                channel.basicPublish("",Constants.PUBLISHER_CONFIRMS_QUEUE3, null, msg.getBytes());
                confirmSeqNo.add(seqNo);
            }
            while (!confirmSeqNo.isEmpty()){
                Thread.sleep(10);
            }
            long end = System.currentTimeMillis();
            System.out.printf("异步确认策略, 消息条数: %d, 耗时: %d ms \n",MESSAGE_COUNT, end-start);
        }
    }

    /**
     * 批量确认
     */
    private static void publishingMessagesInBatches() throws Exception{
        try(Connection connection = createConnection()) {
            //1. 开启信道
            Channel channel = connection.createChannel();
            //2. 设置信道为confirm模式
            channel.confirmSelect();
            //3. 声明队列
            channel.queueDeclare(Constants.PUBLISHER_CONFIRMS_QUEUE2, true, false, false, null);
            //4. 发送消息, 并进行确认
            long start = System.currentTimeMillis();
            int batchSize = 100;
            int outstandingMessageCount = 0;
            for (int i = 0; i < MESSAGE_COUNT; i++) {
                String msg = "hello publisher confirms"+i;
                channel.basicPublish("",Constants.PUBLISHER_CONFIRMS_QUEUE2, null, msg.getBytes());
                outstandingMessageCount++;
                if (outstandingMessageCount==batchSize){
                    channel.waitForConfirmsOrDie(5000);
                    outstandingMessageCount = 0;
                }
            }
            if (outstandingMessageCount>0){
                channel.waitForConfirmsOrDie(5000);
            }
            long end = System.currentTimeMillis();
            System.out.printf("批量确认策略, 消息条数: %d, 耗时: %d ms \n",MESSAGE_COUNT, end-start);

        }
    }

    /**
     * 单独确认
     */
    private static void publishingMessagesIndividually() throws Exception{
        try(Connection connection = createConnection()) {
            //1. 开启信道
            Channel channel = connection.createChannel();
            //2. 设置信道为confirm模式
            channel.confirmSelect();
            //3. 声明队列
            channel.queueDeclare(Constants.PUBLISHER_CONFIRMS_QUEUE1, true, false, false, null);
            //4. 发送消息, 并等待确认
            long start = System.currentTimeMillis();
            for (int i = 0; i < MESSAGE_COUNT; i++) {
                String msg = "hello publisher confirms"+i;
                channel.basicPublish("",Constants.PUBLISHER_CONFIRMS_QUEUE1, null, msg.getBytes());
                //等待确认
                channel.waitForConfirmsOrDie(5000);
            }
            long end = System.currentTimeMillis();
            System.out.printf("单独确认策略, 消息条数: %d, 耗时: %d ms \n",MESSAGE_COUNT, end-start);
        }
    }
}
相关推荐
用户8307196840821 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者2 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者4 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧5 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖5 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农5 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者5 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端
业精于勤_荒于稀5 天前
物流订单系统99.99%可用性全链路容灾体系落地操作手册
分布式
Ronin3055 天前
信道管理模块和异步线程模块
开发语言·c++·rabbitmq·异步线程·信道管理
Asher05095 天前
Hadoop核心技术与实战指南
大数据·hadoop·分布式