RabbitMQ 工作模式使用案例之(发布订阅模式、路由模式、通配符模式)

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~

🌱🌱个人主页:奋斗的明志

🌱🌱所属专栏:RabbitMQ
📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。

发布订阅模式、路由模式、通配符模式

一、Publish/Subscribe(发布/订阅)

在发布/订阅模型中,多了一个Exchange角色.
Exchange 常见有三种类型, 分别代表不同的路由规则

a) Fanout:广播,将消息交给所有绑定到交换机的队列 (Publish/Subscribe模式)

b) Direct:定向,把消息交给符合指定routing key的队列(Routing模式)

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

也就分别对应不同的工作模式

1、引入依赖


java 复制代码
<dependencies>
        <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.20.0</version>
        </dependency>
</dependencies>

2、编写配置类

java 复制代码
package rabbitmq.constant;

public class Constants {
    public static final String HOST = "123.57.16.61";
    public static final Integer PORT = 5672;
    public static final String USERNAME = "study";
    public static final String PASSWORD = "study";
    public static final String VIRTUAL_HOST = "bite";
    //发布订阅模式
    public static final String FANOUT_EXCHANGE = "fanout.exchange";
    public static final String FANOUT_QUEUE1 = "fanout.queue1";
    public static final String FANOUT_QUEUE2 = "fanout.queue2";
}

3、编写生产者代码

java 复制代码
package rabbitmq.fanout;

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 {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换机
        /**
         * 交换机名称,交换机类型,开启可持久化(关机数据不会丢失)
         */
        channel.exchangeDeclare(Constants.FANOUT_EXCHANGE, BuiltinExchangeType.FANOUT, true);
        //声明队列
        //queueDeclare 队列声明
        channel.queueDeclare(Constants.FANOUT_QUEUE1, true, false, false, null);
        channel.queueDeclare(Constants.FANOUT_QUEUE2, true, false, false, null);

        //交换机和队列进行绑定
        channel.queueBind(Constants.FANOUT_QUEUE1, Constants.FANOUT_EXCHANGE, "");
        channel.queueBind(Constants.FANOUT_QUEUE2, Constants.FANOUT_EXCHANGE, "");
        //发布消息
        String msg = "hello fanout...";
        //basicPublish (基础发布)
        channel.basicPublish(Constants.FANOUT_EXCHANGE, "", null, msg.getBytes());
        System.out.println("消息发送成功!!!");

        //关闭资源
        channel.close();
        connection.close();
    }
}

点击运行:



4、编写消费者代码

消费者1:

java 复制代码
package rabbitmq.fanout;

import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明队列
        //queueDeclare 队列声明 (也可以省略)
        channel.queueDeclare(Constants.FANOUT_QUEUE1, true, false, false, null);
        //消费消息
        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);

    }
}

消费者2:

java 复制代码
package rabbitmq.fanout;

import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer2 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明队列
        //queueDeclare 队列声明 (也可以省略)
        channel.queueDeclare(Constants.FANOUT_QUEUE2, true, false, false, null);
        //消费消息
        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_QUEUE2,true,consumer);

    }
}

二、Routing (路由模式)

队列和交换机的绑定, 不能是任意的绑定了, 而是要指定⼀个BindingKey(RoutingKey的⼀种)

消息的发送方在向 Exchange 发送消息时, 也需要指定消息的 RoutingKey
Exchange也不再把消息交给每⼀个绑定的key, 而是根据消息的RoutingKey进行判断, 只有队列绑定时的BindingKey和发送消息的RoutingKey 完全⼀致, 才会接收到消息

1、引入依赖


java 复制代码
<dependencies>
        <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.20.0</version>
        </dependency>
</dependencies>

2、编写配置类

java 复制代码
package rabbitmq.constant;

public class Constants {
    public static final String HOST = "123.57.16.61";
    public static final Integer PORT = 5672;
    public static final String USERNAME = "study";
    public static final String PASSWORD = "study";
    public static final String VIRTUAL_HOST = "bite";

    //路由模式
    public static final String DIRECT_EXCHANGE = "direct.exchange";
    public static final String DIRECT_QUEUE1 = "direct.queue1";
    public static final String DIRECT_QUEUE2 = "direct.queue2";
}

3、编写生产者代码

java 复制代码
package rabbitmq.direct;

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 {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换机
        /**
         * 交换机名称,交换机类型,开启可持久化(关机数据不会丢失)
         */
        channel.exchangeDeclare(Constants.DIRECT_EXCHANGE, BuiltinExchangeType.DIRECT, true);
        //声明队列
        //queueDeclare 队列声明
        channel.queueDeclare(Constants.DIRECT_QUEUE1, true, false, false, null);
        channel.queueDeclare(Constants.DIRECT_QUEUE2, true, false, false, null);

        //交换机和队列进行绑定
        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");


        //发布消息
        String msg_a = "hello direct, my routingkey is a...";
        //basicPublish (基础发布)
        channel.basicPublish(Constants.DIRECT_EXCHANGE, "", null, msg_a.getBytes());

        String msg_b = "hello direct, my routingkey is b...";
        channel.basicPublish(Constants.DIRECT_EXCHANGE, "", null, msg_b.getBytes());

        String msg_c = "hello direct, my routingkey is c...";
        channel.basicPublish(Constants.DIRECT_EXCHANGE, "", null, msg_c.getBytes());

        System.out.println("消息发送成功!!!");

        //关闭资源
        channel.close();
        connection.close();
    }
}




4、编写消费者代码

消费者1:

java 复制代码
package rabbitmq.direct;

import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明队列
        //queueDeclare 队列声明 (也可以省略)
        channel.queueDeclare(Constants.DIRECT_QUEUE1, true, false, false, null);
        //消费消息
        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);
    }
}

消费者2:

java 复制代码
package rabbitmq.direct;

import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer2 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明队列
        //queueDeclare 队列声明 (也可以省略)
        channel.queueDeclare(Constants.DIRECT_QUEUE2, true, false, false, null);
        //消费消息
        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_QUEUE2,true,consumer);
    }
}

三、Topics (通配符模式)

Topics 和Routing模式的区别是:

  1. topics 模式使用的交换机类型为topic(Routing模式使用的交换机类型为direct)
  2. topic 类型的交换机在匹配规则上进行了扩展, Binding Key⽀持通配符匹配(direct类型的交换机路由规则是BindingKey和RoutingKey完全匹配)

在topic类型的交换机在匹配规则上, 有些要求:

  1. RoutingKey 是⼀系列由点( . )分隔的单词, ⽐如 " stock.usd.nyse ", " nyse.vmw ",
    " quick.orange.rabbit "
  2. BindingKey 和RoutingKey⼀样, 也是点( . )分割的字符串.
  3. Binding Key中可以存在两种特殊字符串, 用于模糊匹配
复制代码
  * 表⽰⼀个单词 # 表⽰多个单词(0-N个)

比如:

• Binding Key 为"d.a.b" 会同时路由到Q1 和Q2

• Binding Key 为"d.a.f" 会路由到Q1

• Binding Key 为"c.e.f" 会路由到Q2

• Binding Key 为"d.b.f" 会被丢弃, 或者返回给⽣产者(需要设置mandatory参数)

1、引入依赖


java 复制代码
<dependencies>
        <!-- https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.20.0</version>
        </dependency>
</dependencies>

2、编写配置类

java 复制代码
package rabbitmq.constant;

public class Constants {
    public static final String HOST = "123.57.16.61";
    public static final Integer PORT = 5672;
    public static final String USERNAME = "study";
    public static final String PASSWORD = "study";
    public static final String VIRTUAL_HOST = "bite";

    //通配符模式
    public static final String TOPIC_EXCHANGE = "topic.exchange";
    public static final String TOPIC_QUEUE1 = "topic.queue1";
    public static final String TOPIC_QUEUE2 = "topic.queue2";

3、编写生产者代码

java 复制代码
package rabbitmq.topic;

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 {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明交换机
        /**
         * 交换机名称,交换机类型,开启可持久化(关机数据不会丢失)
         */
        channel.exchangeDeclare(Constants.TOPIC_EXCHANGE, BuiltinExchangeType.TOPIC, true);
        //声明队列
        //queueDeclare 队列声明
        channel.queueDeclare(Constants.TOPIC_QUEUE1, true, false, false, null);
        channel.queueDeclare(Constants.TOPIC_QUEUE2, true, false, false, null);

        //交换机和队列进行绑定
        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.#");


        //发布消息
        String msg_a = "hello topic, my routingkey is ae.a.f...";
        //basicPublish (基础发布)
        channel.basicPublish(Constants.TOPIC_EXCHANGE, "ae.a.f", null, msg_a.getBytes());

        String msg_b = "hello topic, my routingkey is ef.a.b...";
        channel.basicPublish(Constants.TOPIC_EXCHANGE, "ef.a.b", null, msg_b.getBytes());

        String msg_c = "hello topic, my routingkey is c.ef.b...";
        channel.basicPublish(Constants.TOPIC_EXCHANGE, "c.ef.b", null, msg_c.getBytes());

        System.out.println("消息发送成功!!!");

        //关闭资源
        channel.close();
        connection.close();
    }
}

4、编写消费者代码

消费者1:

java 复制代码
package rabbitmq.topic;

import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明队列
        //queueDeclare 队列声明 (也可以省略)
        channel.queueDeclare(Constants.TOPIC_QUEUE1, true, false, false, null);
        //消费消息
        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);
    }
}

消费者2:

java 复制代码
package rabbitmq.topic;

import com.rabbitmq.client.*;
import rabbitmq.constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer2 {
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost(Constants.HOST);
        connectionFactory.setPort(Constants.PORT);
        connectionFactory.setUsername(Constants.USERNAME);
        connectionFactory.setPassword(Constants.PASSWORD);
        connectionFactory.setVirtualHost(Constants.VIRTUAL_HOST);
        Connection connection = connectionFactory.newConnection();
        Channel channel = connection.createChannel();
        //声明队列
        //queueDeclare 队列声明 (也可以省略)
        channel.queueDeclare(Constants.TOPIC_QUEUE2, true, false, false, null);
        //消费消息
        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_QUEUE2,true,consumer);
    }
}
相关推荐
小夏子_riotous8 小时前
Docker学习路径——2、安装
linux·运维·分布式·学习·docker·容器·云计算
Jackyzhe12 小时前
从零学习Kafka:认证机制
分布式·学习·kafka
java修仙传13 小时前
从手写 Redis 锁到 Redisson:我对分布式锁安全性的理解
java·数据库·redis·分布式
juniperhan16 小时前
Flink 系列第10篇:Flink 分布式缓存详解
分布式·缓存·flink
ldj202017 小时前
从 API 调用到事件驱动:用 RabbitMQ /RocketMQ重构微服务通信架构
架构·rabbitmq
gihigo199818 小时前
分布式发电的配电网有功-无功综合优化 MATLAB 实现
开发语言·分布式·matlab
脑子加油站18 小时前
OpenEuler24.03 分布式配置redis 集群
数据库·redis·分布式·php·nginx代理
想你依然心痛20 小时前
HarmonyOS 5.0工业物联网开发实战:构建分布式智能制造监控与数字孪生预测维护系统
分布式·物联网·harmonyos·数字孪生
zhixingheyi_tian20 小时前
Hadoop 之 native 库
大数据·linux·hadoop·分布式
蓝魔Y20 小时前
Apache—Kafka实践
分布式·kafka·apache