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);
        }
    }
}
相关推荐
ALex_zry3 小时前
Redis Cluster 分布式缓存架构设计与实践
redis·分布式·缓存
为什么不问问神奇的海螺呢丶5 小时前
n9e categraf rabbitmq监控配置
分布式·rabbitmq·ruby
TTBIGDATA9 小时前
【Atlas】Atlas Hook 消费 Kafka 报错:GroupAuthorizationException
hadoop·分布式·kafka·ambari·hdp·linq·ranger
m0_6873998412 小时前
telnet localhost 15672 RabbitMQ “Connection refused“ 错误表示目标主机拒绝了连接请求。
分布式·rabbitmq
陌上丨12 小时前
生产环境分布式锁的常见问题和解决方案有哪些?
分布式
新新学长搞科研12 小时前
【智慧城市专题IEEE会议】第六届物联网与智慧城市国际学术会议(IoTSC 2026)
人工智能·分布式·科技·物联网·云计算·智慧城市·学术会议
Ronin30512 小时前
日志打印和实用 Helper 工具
数据库·sqlite·rabbitmq·文件操作·uuid生成
泡泡以安12 小时前
Scrapy分布式爬虫调度器架构设计说明
分布式·爬虫·scrapy·调度器
没有bug.的程序员14 小时前
RocketMQ 与 Kafka 深度对垒:分布式消息引擎内核、事务金融级实战与高可用演进指南
java·分布式·kafka·rocketmq·分布式消息·引擎内核·事务金融
上海锟联科技14 小时前
250MSPS DAS 在地铁监测中够用吗?——来自上海锟联科技的工程实践
分布式·科技·分布式光纤传感·das解调卡·光频域反射·das