掌控消息全链路(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);
    }
}
相关推荐
子非衣1 天前
CenOS7安装RabbitMQ(含延迟队列插件)
分布式·rabbitmq·ruby
独自破碎E1 天前
说说RabbitMQ的集群模式
rabbitmq
利刃大大1 天前
【RabbitMQ】重试机制 && TTL && 死信队列
分布式·后端·消息队列·rabbitmq·队列
论迹2 天前
【RabbitMQ】-- 七种工作模式
分布式·rabbitmq
论迹2 天前
【RabbitMQ】-- 高级特性
数据库·redis·分布式·消息队列·rabbitmq
我爱娃哈哈2 天前
SpringBoot + Canal + RabbitMQ:MySQL 数据变更实时同步到缓存与搜索系统
spring boot·rabbitmq·java-rabbitmq
利刃大大2 天前
【RabbitMQ】消息确认机制 && 持久化 && 发布确认机制
分布式·中间件·消息队列·rabbitmq·mq
xiaolyuh1232 天前
RabbitMQ 深度详解
分布式·rabbitmq
Overt0p2 天前
抽奖系统(7)
java·开发语言·spring boot·redis·tomcat·rabbitmq