掌控消息全链路(1)——初识RabbitMQ:从核心概念到五种常用模式全景解析


🔥我的主页: 九转苍翎
⭐️个人专栏: 《Java SE 》 《Java集合框架系统精讲》 《MySQL高手之路:从基础到高阶 》 《计算机网络 》 《Java工程师核心能力体系构建》
天行健,君子以自强不息。


Linux操作系统版本:Ubuntu 24.04 LTS

1.Message Queue概述

计算机之间的通信方式主要有两种:同步通信异步通信

  • 同步通信(Synchronous Communication):通信双方在严格的时间约束下进行交互。发送方发送请求或数据后,会主动等待并阻塞自身,直到收到接收方的明确响应(成功、失败或超时)才会继续执行后续操作。整个过程像是在进行一场"实时对话"
  • 异步通信(Asynchronous Communication):发送方发出请求或消息后,不等待接收方的即时响应,而是立即返回并继续执行后续任务。接收方在准备好结果后,通过某种机制将响应或结果"推送"或"通知"给发送方。整个过程更像是"发送邮件"。

MQ(Message Queue,消息队列)是一种用于实现异步通信 的中间件技术。它允许不同组件(例如应用程序、服务或微服务)通过发送和接收消息来进行通信,而无需实时等待响应。核心思想是解耦生产者(发送消息)和消费者(接收消息)之间的关系。其核心功能如下:

  • 异步解耦 :生产者和消费者不需要知道对方的存在或状态。生产者只需将消息发送到队列,消费者在准备好时从队列中获取消息进行处理
  • 削峰填谷(缓冲) :当消费者处理能力有限或暂时不可用时,队列可以作为缓冲区,暂存生产者发送的大量消息,避免系统过载或消息丢失。待消费者恢复或扩展后,再逐步消费积压的消息

2.初识RabbitMQ

AMQP是一个开放标准的应用层协议,设计用于异步、可靠、跨平台的消息传递。它定义了消息的格式、传递机制和路由规则,是构建分布式系统中消息中间件的核心协议

RabbitMQ是采用Erlang语言实现 AMQP(Advanced Message Queuing Protocol,高级消息队列协议) 的消息中间件

2.1 安装

  • 安装erlang

    bash 复制代码
    # 更新软件包
    root@VM-0-7-ubuntu:~# apt-get update
    # 安装erlang
    root@VM-0-7-ubuntu:~# apt-get install erlang
    # 查看erlang版本,输入 "erl" 会启动Erlang 运行时系统
    root@VM-0-7-ubuntu:~# erl
    # 输入 "halt()." 立即停止Erlang运行时系统
    1> halt().
  • 安装RabbitMQ

    bash 复制代码
    # 安装RabbitMQ
    root@VM-0-7-ubuntu:~# apt-get install rabbitmq-server
    # 确认安装结果
    root@VM-0-7-ubuntu:~# systemctl status rabbitmq-server
  • 安装RabbitMQ管理界面

    bash 复制代码
    root@VM-0-7-ubuntu:~# rabbitmq-plugins enable rabbitmq_management
  • 启动RabbitMQ

    bash 复制代码
    root@VM-0-7-ubuntu:~# service rabbitmq-server start

2.2 访问

  • 5672 端口是 RabbitMQ 的默认 AMQP协议端口。生产者和消费者通过此端口与 RabbitMQ 交互
  • 15672 端口是 RabbitMQ 管理插件的默认 HTTP 端口。通过此端口可以访问 RabbitMQ 的 Web 管理界面,提供图形化的管理功能

添加管理员用户

bash 复制代码
# 添加用户:add_user ${账号} ${密码}
root@VM-0-7-ubuntu:~# rabbitmqctl add_user admin admin
# 用户授权:set_user_tags ${账号} ${权限}
root@VM-0-7-ubuntu:~# rabbitmqctl set_user_tags admin administrator

登录页面

首页

2.3 工作流程

RabbitMQ 组件 邮局系统类比 作用
Broker(代理) 整个邮局 整个消息队列系统,包含所有组件
Virtual Host(虚拟主机) 不同地域的邮局分局 逻辑隔离,每个 vhost 有独立的用户/权限/队列
Connection(连接) 电话专线 生产者和消费者之间的 TCP 连接
Channel(信道) 分机电话 虚拟连接,复用同一个 TCP 连接
Exchange(交换机) 邮件分拣中心 接收消息并决定路由到哪个队列
Queue(队列) 收件人的邮箱 存储消息等待消费者取走
Binding(绑定) 分拣规则 交换机和队列之间的路由规则

第一阶段:连接建立

  1. 建立 TCP 连接

    • 生产者应用程序首先与 Broker 建立 TCP 连接,默认端口为 5672
    • 连接需要指定虚拟主机、用户名和密码
  2. 创建信道

    • 在已建立的 TCP 连接上创建一个或多个信道
    • 信道是虚拟连接,共享同一个 TCP 连接。每个信道有独立的通信流,相互隔离
      第二阶段:资源声明
  3. 声明交换机:指定名称、类型和属性

  4. 声明队列:指定名称和属性

  5. 创建绑定:将队列绑定到交换机,并指定绑定键(Binding Key)
    第三阶段:消息发送

  6. 发送消息到交换机:将消息发布到指定的交换机。消息包含:交换机名称、路由键、消息体、消息属性

  7. 交换机路由消息:交换机接收消息后,根据其类型和绑定规则进行路由
    第四阶段:路由处理

  8. 成功路由:队列接收并存储消息,等待消费者拉取或推送消息给消费者

3.RabbitMQ七种工作模式

3.0 常量类

java 复制代码
public class Constants {
    public static final String HOST = "81.69.218.112";
    public static final int PORT = 5672;
    public static final String USER_NAME = "study";
    public static final String PASSWORD = "study";
    public static final String VIRTUAL_HOST = "org";
    //工作队列模式
    public static final String WORK_QUEUE = "work_queue";
    //发布订阅模式
    public static final String FANOUT_EXCHANGE = "fanout_exchange";
    public static final String FANOUT_QUEUE1 = "fanout_queue1";
    public static final String FANOUT_QUEUE2 = "fanout_queue2";
    //路由模式
    public static final String DIRECT_EXCHANGE = "direct_exchange";
    public static final String DIRECT_QUEUE1 = "direct_queue1";
    public static final String DIRECT_QUEUE2 = "direct_queue2";
    //通配符模式
    public static final String TOPIC_EXCHANGE = "topic_exchange";
    public static final String TOPIC_QUEUE1 = "topic_queue1";
    public static final String TOPIC_QUEUE2 = "topic_queue2";
    //rpc模式
    public static final String RPC_REQUEST_QUEUE = "rpc_request_queue";
    public static final String RPC_RESPONSE_QUEUE = "rpc_response_queue";
    //发布确认模式
    public static final String PUBLISHER_CONFIRM_QUEUE1 = "publisher_confirm_queue1";
    public static final String PUBLISHER_CONFIRM_QUEUE2 = "publisher_confirm_queue2";
    public static final String PUBLISHER_CONFIRM_QUEUE3 = "publisher_confirm_queue3";
}

3.1 Simple

核心特征:

  • 最简单的消息队列模式
  • 一个生产者,一个消费者,一个队列

工作流程:

代码实现:

java 复制代码
/**
 * 生产者
 */
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //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.声明队列
        /*
          queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments)
        queue:队列名称
        durable:可持久化
        exclusive:是否独占
        autoDelete:是否自动删除
        arguments:参数,暂不介绍
         */
        channel.queueDeclare(Constants.WORK_QUEUE,true,false,false,null);
        //5.发送消息
        for (int i = 0; i < 10; i++) {
            channel.basicPublish("", Constants.WORK_QUEUE, null, ("Hello RabbitMQ!" + i).getBytes());
        }
        System.out.println("消息发送成功");
        //6.资源释放
        channel.close();
        connection.close();
    }
}
/**
 * 消费者
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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.声明队列
        /*
          queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
                                 Map<String, Object> arguments)
        queue:队列名称
        durable:可持久化
        exclusive:是否独占
        autoDelete:是否自动删除
        arguments:参数,暂不介绍
         */
        channel.queueDeclare("first",true,false,false,null);
        //5. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.WORK_QUEUE,true,defaultConsumer);
        Thread.sleep(2000);
        //6.资源释放
        channel.close();
        connection.close();
    }
}

3.2 Work Queues

核心特征:

  • 多个消费者竞争消费同一个队列
  • 轮询分发(默认):每个消费者依次接收消息

工作流程:

代码实现:

java 复制代码
/**
 * 生产者
 */
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //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(Constants.WORK_QUEUE,true,false,false,null);
        //5.发送消息
        for (int i = 0; i < 10; i++) {
            channel.basicPublish("", Constants.WORK_QUEUE, null, ("Hello RabbitMQ!:" + i).getBytes());
        }
        System.out.println("消息发送成功");
        //6.资源释放
        channel.close();
        connection.close();
    }
}
/**
 * 消费者A
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerA {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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(Constants.WORK_QUEUE,true,false,false,null);
        //5. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("ConsumerA 接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.WORK_QUEUE,true,defaultConsumer);
        Thread.sleep(2000);
        //6.资源释放
//        channel.close();
//        connection.close();
    }
}
/**
 * 消费者B
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerB {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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(Constants.WORK_QUEUE,true,false,false,null);
        //5. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("ConsumerB 接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.WORK_QUEUE,true,defaultConsumer);
        Thread.sleep(2000);
        //6.资源释放
//        channel.close();
//        connection.close();
    }
}

3.3 Publish/Subscribe

核心特征:

  • 一条消息被多个消费者接收
  • 消息广播到所有绑定队列

工作流程:

代码实现:

java 复制代码
/**
 * 生产者
 */
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //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.声明交换机
        //BuiltinExchangeType.FANOUT:广播类型,将消息交给所有绑定到交换机的队列
        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.发送消息
        for (int i = 0; i < 10; i++) {
            channel.basicPublish(Constants.FANOUT_EXCHANGE, "", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        System.out.println("消息发送成功");
        //7.资源释放
        channel.close();
        connection.close();
    }
}
/**
 * 消费者A
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerA {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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);
        //4. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.FANOUT_QUEUE1,true,defaultConsumer);
        Thread.sleep(2000);
    }
}
/**
 * 消费者B
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerB {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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_QUEUE2,true,false,false,null);
        //4. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.FANOUT_QUEUE2,true,defaultConsumer);
        Thread.sleep(2000);
    }
}

3.4 Routing

核心特征:

  • 根据路由键选择性接收消息
  • 精确匹配路由键

工作流程:
代码实现:

java 复制代码
/**
 * 生产者
 */
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //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.声明交换机
        //BuiltinExchangeType.DIRECT:定向类型,把消息交给符合指定binding key的队列
        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.发送消息
        for (int i = 0; i < 3; i++) {
            channel.basicPublish(Constants.DIRECT_EXCHANGE, "a", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        for (int i = 0; i < 3; i++) {
            channel.basicPublish(Constants.DIRECT_EXCHANGE, "b", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        for (int i = 0; i < 3; i++) {
            channel.basicPublish(Constants.DIRECT_EXCHANGE, "c", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        System.out.println("消息发送成功");
        //7.资源释放
        channel.close();
        connection.close();
    }
}
/**
 * 消费者A
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerA {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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);
        //4. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.DIRECT_QUEUE1,true,defaultConsumer);
        Thread.sleep(2000);
    }
}
/**
 * 消费者B
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerB {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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_QUEUE2,true,false,false,null);
        //4. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.DIRECT_QUEUE2,true,defaultConsumer);
        Thread.sleep(2000);
    }
}

3.5 Topics

核心特征:

  • 根据路由键选择性接收消息
  • 支持通配符匹配
  • 通配符规则
    • *(星号):匹配一个单词

    • #(井号):匹配零个或多个单词

    • 单词用点号分隔,如stock.usd.nyse

工作流程:
代码实现:与Routing模式基本一致

java 复制代码
/**
 * 生产者
 */
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        //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.声明交换机
        //BuiltinExchangeType.TOPIC:通配符类型,把消息交给符合routing pattern(路由模式)的队列
        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.发送消息
        for (int i = 0; i < 3; i++) {
            //转发到queue1
            channel.basicPublish(Constants.TOPIC_EXCHANGE, "aa.a.f", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        for (int i = 0; i < 3; i++) {
            //转发到queue1和queue2
            channel.basicPublish(Constants.TOPIC_EXCHANGE, "aa.a.b", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        for (int i = 0; i < 3; i++) {
            //转发到queue2
            channel.basicPublish(Constants.TOPIC_EXCHANGE, "c.a.a.a", null, ("Hello RabbitMQ!" + i).getBytes());
        }
        System.out.println("消息发送成功");
        //7.资源释放
        channel.close();
        connection.close();
    }
}
/**
 * 消费者A
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerA {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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);
        //4. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.TOPIC_QUEUE1,true,defaultConsumer);
        Thread.sleep(2000);
    }
}
/**
 * 消费者B
 */
import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConsumerB {
    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        //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_QUEUE2,true,false,false,null);
        //4. 消费消息
        DefaultConsumer defaultConsumer = new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) {
                //TODO
                System.out.println("接收到消息:" + new String(body));
            }
        };
        channel.basicConsume(Constants.TOPIC_QUEUE2,true,defaultConsumer);
        Thread.sleep(2000);
    }
}
相关推荐
为什么不问问神奇的海螺呢丶3 小时前
n9e categraf rabbitmq监控配置
分布式·rabbitmq·ruby
m0_687399849 小时前
telnet localhost 15672 RabbitMQ “Connection refused“ 错误表示目标主机拒绝了连接请求。
分布式·rabbitmq
Ronin3059 小时前
日志打印和实用 Helper 工具
数据库·sqlite·rabbitmq·文件操作·uuid生成
坊钰3 天前
【Rabbit MQ】Rabbit MQ 的结构详解,传输机制!!!
java·rabbitmq
请叫我头头哥3 天前
SpringBoot进阶教程(八十九)rabbitmq长链接及域名TTL,多机房切换配置重连能力
rabbitmq·springboot
三水不滴3 天前
对比一下RabbitMQ和RocketMQ
经验分享·笔记·分布式·rabbitmq·rocketmq
JP-Destiny4 天前
后端-RabbitMQ
后端·消息队列·rabbitmq·java-rabbitmq
AC赳赳老秦4 天前
DeepSeek 辅助科研项目申报:可行性报告与经费预算框架的智能化撰写指南
数据库·人工智能·科技·mongodb·ui·rabbitmq·deepseek
Knight_AL4 天前
线程池满了怎么办?用 RabbitMQ 做任务补偿不丢失
分布式·rabbitmq·ruby
坊钰4 天前
【Rabbit MQ】Rabbit MQ 介绍
java·rabbitmq