RabbitMQ的工作模式分类
RabbitMQ工作模式
官网
地址:https://www.rabbitmq.com/getstarted.html
查看RabbitMQ工作模式:
说明
查看RabbitMQ工作模式说明:
RabbitMQ工作模式:
1、简单模式HelloWorld: 一个生产者、一个消费者,不需要设置交换机(使用默认的交换机)
P Producer 生产者: 发送消息到队列
C Consumer 消费者: 消费队列消息
2、工作队列模式Work Queue 一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)
3、发布订阅模式Publish/subscribe,需要设置类型为fanout的交换机,并且交换机和队列进行绑定,当发送消息到交换机后,交换机会将消息发送到绑定的队列
X Exchange 交换机
4、路由模式Routing 需要设置类型为direct的交换机,交换机和队列进行绑定,并且指定routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列
5、通配符模式Topic需要设置类型为topic的交换机,交换机和队列进行绑定,并且指定通配符方式routing key,当发送消息到交换机后,交换机会根据routing key将消息发送到对应的队列
RabbitMQ工作模式-简单模式(一)消息生产者
目标
编写消息生产者代码,发送消息到队列
环境准备
-
访问控制台主页:http://192.168.12.132:15672
创建用户:heima
创建虚拟主机:/itcast
给虚拟主机分配heima用户的访问权限
-
创建heima-rabbitmq的工程;添加用于操作rabbitMQ的依赖;
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
分析
生产者发送消息到RabbitMQ的某个队列,消费者从队列中获取消息。可以使用rabbitMQ的简单模式(simple);生产者发送消息步骤:
-
创建连接工厂(设置连接相关参数);
-
创建连接;
-
创建频道;
-
声明队列;
-
发送消息;
-
关闭资源;
实现
package cn.itcast.rabbitmq.a_simple;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer {
static final String SIMPLE_QUEUE = "simple_queue";
public static void main(String[] args) throws Exception {
//1. 创建连接工厂(设置连接相关参数);
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
factory.setVirtualHost("/itcast");
factory.setUsername("heima");
factory.setPassword("888");
//2. 创建连接;
Connection connection = factory.newConnection();
//3. 创建频道;
Channel channel = connection.createChannel();
//4. 声明队列;
// 参数1:队列名称
// 参数2:是否持久化
// 参数3:是否独占本次连接
// 参数4:是否自动删除
// 参数5:其他参数
channel.queueDeclare(SIMPLE_QUEUE,true,false,false,null);
//5. 发送消息;
// 参数1:交换机,简单模式可以不传
// 参数2:路由key,简单模式要指定为队列名称即可
// 参数3:消息参数
// 参数4:消息内容
channel.basicPublish("",SIMPLE_QUEUE,null,"Hello,Rabbit!".getBytes());
//6. 关闭资源;
channel.close();
connection.close();
}
}
小结
window下的本机rabbitmq中,在设置连接工厂的时候;如果没有指定连接的一系列参数的话;那么会有默认值。主要去设置虚拟主机。
RabbitMQ工作模式-简单模式(二)消息消费者
目标
编写消息消费者代码,从队列中接收消息并消费
分析
从RabbitMQ的队列中接受消息;实现消息消费者:
-
创建连接工厂;
-
创建连接;
-
创建频道;
-
声明队列;
-
创建消费者(接受消息并处理消息);
-
监听消息队列
实现
第一步:消息的消费者,也需要创建连接对象,这些代码与消息的生产者中创建连接的代码是一样的。所以,这里抽取出工具类返回连接对象后,再实现消息消费。
package cn.itcast.rabbitmq.util;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class ConnectionUtil {
public static Connection getConnection() throws IOException, TimeoutException {
//1. 创建连接工厂(设置连接相关参数);
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
factory.setPort(5672);
factory.setVirtualHost("/itcast");
factory.setUsername("heima");
factory.setPassword("888");
//2. 创建连接;
return factory.newConnection();
}
}
第二步:实现消息消费
package cn.itcast.rabbitmq.a_simple;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1. 创建连接工厂;
//2. 创建连接;
Connection connection = ConnectionUtil.getConnection();
//3. 创建频道;
Channel channel = connection.createChannel();
//4. 声明队列; (如果队列已经存在,省略此队列)
//5. 创建消费者(接受消息并处理消息);
DefaultConsumer consumer = new DefaultConsumer(channel){
注意
在启动消息监听之后不要把资源关闭。
RabbitMQ工作模式-简单模式(二)测试
目标
启动消费者和生产者,到RabbitMQ中查询队列并在消费者端IDEA控制台查看接收到的消息
分析
生产者发送消息到rabbitMQ队列(simple_queue),消费者从队列中接收消息;使用了简单模式(simple)
小结
简单模式:
-
生产者发送消息到队列中,消费者从队列中接收消息;
-
在rabbitMQ中消费者只能从队列中接收到消息。
-
思考:如果接收消息的消费者在同一个队列中有多个时,消息是如何分配的?
RabbitMQ工作模式-Work queues工作队列模式
目标
编写生产者、消费者代码并测试了解Work queues工作队列模式的特点
分析
工作队列模式Work Queue: 一个生产者、多个消费者(竞争关系),不需要设置交换机(使用默认的交换机)
-
在同一个队列中可以有多个消费者监听消息;消费者之间对于消息是竞争关系。
-
生产者:发送30个消息;创建两个消费者去监听同一个队列,查看两个消费者接收到的消息是否存在重复。
-
如图
消息生产者
package cn.itcast.rabbitmq.b_workqueue;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
public class Producer {
static final String SIMPLE_QUEUE = "simple_queue";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(SIMPLE_QUEUE,true,false,false,null);
//发送消息;
for (int i = 10; i < 21; i++) {
channel.basicPublish("",SIMPLE_QUEUE,null,("Hello,Rabbit!"+i).getBytes());
}
//关闭资源;
channel.close();
connection.close();
}
}
消息消费者
package cn.itcast.rabbitmq.b_workqueue;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1. 创建连接工厂;
//2. 创建连接;
Connection connection = ConnectionUtil.getConnection();
//3. 创建频道;
Channel channel = connection.createChannel();
//4. 声明队列; (如果队列已经存在,省略此队列)
//5. 创建消费者(接受消息并处理消息);
DefaultConsumer consumer = new DefaultConsumer(channel){
public class Consumer2 {
......
}
小结
工作队列模式:一个消息只能被一个消费者接收,其它消费者不能接收到。
应用场景:在消费者端任务处理时,如果配置了多个消费者可以提高任务处理效率。
RabbitMQ工作模式-订阅模式类型介绍
目标
理解订阅模式中的Exchange交换机作用以及交换机的三种类型。
说明
前面2个案例中,只有3个角色: P:生产者,也就是要发送消息的程序 C:消费者:消息的接受者,会一直等待消息到来。 queue:消息队列,图中红色部分
而在订阅模型中,多了一个exchange角色,而且过程略有变化:
-
P:生产者,也就是要发送消息的程序,但是不再发送到队列中,而是发给X(交换机)
-
C:消费者,消息的接受者,会一直等待消息到来。
-
Queue:消息队列,接收消息、缓存消息。
-
Exchange:交换机,图中的X。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如把消息递交给某个特别队列、递交给所有队列、或是将消息丢弃。 到底如何操作,取决于Exchange的类型。Exchange有常见以下3种类型:
-
Fanout:广播,将消息交给所有绑定到交换机的队列
-
Direct:定向,把消息交给符合指定routing key 的队列
-
Topic:通配符,把消息交给符合routing pattern(路由模式) 的队列Exchange(交换机)只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息会丢失!
-
订阅模式示例图:
图1:交换机类型为Fanout
图2:交换机类型为Direct
图3:交换机类型为Topic
小结
订阅模式与前面的模式多了一个角色:Exchange交换机,接收数据并决定如何将数据转发投递到不同的队列;消息的投递决定于交换机的类型。
Exchange交换机的类型:广播fanout,定向direct,通配符topic
交换机是只做消息的转发投递,自身不存储数据
RabbitMQ工作模式-Publish/Subscribe发布与订阅模式
目标
编写生产者、消费者代码并测试了解Publish/Subscribe发布与订阅模式的特点
模式说明
-
发布订阅模式:
-
1、每个消费者监听自己的队列。
-
2、生产者将消息发给交换机,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收 到消息
-
3、如图
-
分析
发布与订阅模式特点:一个消息可以被多个消费者接收;其实使用的是订阅模式交换机类型为:广播
-
生产者(发送10个消息)
-
创建连接;
-
创建频道;
-
声明交换机;
-
声明队列;
-
队列绑定到交换机;
-
发送消息;
-
关闭资源
-
消费者(至少要有两个)
-
创建连接;
-
创建频道;
-
声明交换机;
-
声明队列;
-
队列绑定到交换机;
-
创建消费者,处理消息;
-
监听队列;
消息生产者
队列1: fanout_queue_1
队列2: fanout_queue_2
交换机: exchange_fanout
package cn.itcast.rabbitmq.c_ps;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
public class Producer {
static final String FANOUT_QUEUE_1 = "fanout_queue_1";
static final String FANOUT_QUEUE_2 = "fanout_queue_2";
static final String EXCHANGE_FANOUT = "exchange_fanout";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//1. 创建队列
channel.queueDeclare(FANOUT_QUEUE_1,true,false,false,null);
channel.queueDeclare(FANOUT_QUEUE_2,true,false,false,null);
//2. 创建交换机, 指定交换机类型是fanout 广播
channel.exchangeDeclare(EXCHANGE_FANOUT, BuiltinExchangeType.FANOUT);
//3. 队列绑定到交换机
channel.queueBind(FANOUT_QUEUE_1,EXCHANGE_FANOUT,"");
channel.queueBind(FANOUT_QUEUE_2,EXCHANGE_FANOUT,"");
for (int i = 10; i < 21; i++) {
// 通过交换机发送消息 (绑定到交换机上的2个队列都会收到消息)
channel.basicPublish(EXCHANGE_FANOUT,"",null,("Hello,Rabbit!"+i).getBytes());
}
channel.close();
connection.close();
}
}
消息消费者
package cn.itcast.rabbitmq.c_ps;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
//1. 创建连接工厂;
//2. 创建连接;
Connection connection = ConnectionUtil.getConnection();
//3. 创建频道;
Channel channel = connection.createChannel();
//4. 声明队列; (如果队列已经存在,省略此队列)
//5. 创建消费者(接受消息并处理消息);
DefaultConsumer consumer = new DefaultConsumer(channel){
package cn.itcast.rabbitmq.c_ps;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
//1. 创建连接工厂;
//2. 创建连接;
Connection connection = ConnectionUtil.getConnection();
//3. 创建频道;
Channel channel = connection.createChannel();
//4. 声明队列; (如果队列已经存在,省略此队列)
//5. 创建消费者(接受消息并处理消息);
DefaultConsumer consumer = new DefaultConsumer(channel){
小结
发布与订阅:一个消息可以被多个消费者接收,使用了 fanout(广播)类型的交换机。
RabbitMQ工作模式-Routing路由模式
目标
编写生产者、消费者代码并测试了解Routing路由模式的特点
模式说明
路由模式特点:
-
队列与交换机的绑定,不能是任意绑定了,而是要指定一个 RoutingKey (路由key)
-
消息的发送方在 向Exchange发送消息时,也必须指定消息的 RoutingKey 。
-
Exchange不再把消息交给每一个绑定的队列,而是根据消息的 Routing Key 进行判断,只有队列的 Routingkey 与消息的 Routing key 完全一致,才会接收到消息
-
如图
分析
-
在编码上与 Publish/Subscribe发布与订阅模式 的区别是交换机的类型为:Direct,还有队列绑定交换机的时候需要指定routing key。
-
生产者发送两个消息(路由key分别为:insert、update);创建两个消费者,分别绑定的队列中路由为(insert,update);
-
消息路由为insert的会被队列路由绑定为insert的接收并被其消费者接收并消费;
-
消息路由为update的会被队列路由绑定为update的接收并被其消费者接收并消费;
-
消息生产者
package cn.itcast.rabbitmq.d_routing;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
public class Producer {
static final String DIRECT_QUEUE_INSERT = "direct_queue_insert";
static final String DIRECT_QUEUE_UPDATE = "direct_queue_update";
static final String EXCHANGE_DIRECT = "exchange_direct";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//1. 创建队列
channel.queueDeclare(DIRECT_QUEUE_INSERT,true,false,false,null);
channel.queueDeclare(DIRECT_QUEUE_UPDATE,true,false,false,null);
//2. 创建交换机, 指定交换机类型是fanout 广播
channel.exchangeDeclare(EXCHANGE_DIRECT, BuiltinExchangeType.DIRECT);
//3. 队列绑定到交换机
channel.queueBind(DIRECT_QUEUE_INSERT,EXCHANGE_DIRECT,"insert");
channel.queueBind(DIRECT_QUEUE_UPDATE,EXCHANGE_DIRECT,"update");
// 发送消息
channel.basicPublish(EXCHANGE_DIRECT,"insert",null,
"路由key是insert,消息投递到direct_queue_insert队列".getBytes());
channel.basicPublish(EXCHANGE_DIRECT,"update",null,
"路由key是update,消息投递到direct_queue_update队列".getBytes());
channel.close();
connection.close();
}
}
消息消费者
package cn.itcast.rabbitmq.d_routing;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
DefaultConsumer consumer = new DefaultConsumer(channel){
package cn.itcast.rabbitmq.d_routing;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
DefaultConsumer consumer = new DefaultConsumer(channel){
小结
路由模式:可以根据消息的路由key传递到不同的队列,然后实现消息的定向投递到不同消费者。
RabbitMQ工作模式-Topics通配符模式
目标
编写生产者、消费者代码并测试了解Topics通配符模式的特点
模式说明
Topic 类型与 Direct 相比,都是可以根据 RoutingKey 把消息路由到不同的队列。只不过 Topic 类型 Exchange 可 以让队列在绑定 Routing key 的时候使用通配符!
Routingkey 一般都是有一个或多个单词组成,多个单词之间以”.”分割,例如: item.insert 通配符规则:
# 匹配一个或多个词
* 匹配不多不少恰好1个词
举例:
item.# :能够匹配 item.insert.abc 或者 item.insert
item.* :匹配 item.insert, 不能匹配item.insert.abc
如图:
如图:
案例分析
-
生产者:发送消息指定交换机是:exchange_topic, 且路由key分别是 item.insert、item.update、item.delete
-
第一个消费者,监听topic_queue, topic_queue队列绑定到交换机的路由key是item.#, 所以收到3条发送的消息
-
第二个消费者,监听topic_queue_delete, topic_queue_delete队列绑定到交换机的路由key是item.delete,所以只能收到一条消息
消息生产者
package cn.itcast.rabbitmq.e_topic;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
public class Producer {
static final String TOPIC_QUEUE = "topic_queue";
static final String TOPIC_QUEUE_DELETE = "topic_queue_delete";
static final String EXCHANGE_TOPIC = "exchange_topic";
public static void main(String[] args) throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明交换机, 交换机的类型是topic 通配符
channel.exchangeDeclare(EXCHANGE_TOPIC,BuiltinExchangeType.TOPIC);
// 发送消息
channel.basicPublish(EXCHANGE_TOPIC,"item.insert",null,"路由key是item.insert,执行插入".getBytes());
channel.basicPublish(EXCHANGE_TOPIC,"item.update",null,"路由key是item.update,执行修改".getBytes());
channel.basicPublish(EXCHANGE_TOPIC,"item.delete",null,"执行删除操作".getBytes());
channel.close();
connection.close();
}
}
消息消费者
package cn.itcast.rabbitmq.e_topic;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明队列
channel.queueDeclare(Producer.TOPIC_QUEUE,true,false,false,null);
// 绑定
channel.queueBind(Producer.TOPIC_QUEUE,Producer.EXCHANGE_TOPIC,"item.#");
DefaultConsumer consumer = new DefaultConsumer(channel){
package cn.itcast.rabbitmq.e_topic;
import cn.itcast.rabbitmq.util.ConnectionUtil;
import com.rabbitmq.client.*;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
public class Consumer2 {
public static void main(String[] args) throws IOException, TimeoutException {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
// 声明队列
channel.queueDeclare(Producer.TOPIC_QUEUE_DELETE,true,false,false,null);
// 绑定
channel.queueBind(Producer.TOPIC_QUEUE_DELETE,Producer.EXCHANGE_TOPIC,"item.delete");
DefaultConsumer consumer = new DefaultConsumer(channel){
小结
Topic通配符模式:可以根据routing key将消息传递到队列中;其中routing key可以使用 * 和 #,使用了通配符则对应路由key的配置更加灵活。
RabbitMQ模式总结
思考
对比总结RabbitMQ的5种模式特征
总结
-
不使用Exchange交换机(默认交换机)
-
simple简单模式:一个生产者发送消息到队列中由一个消费者接收。
-
work工作队列模式:一个生产者发送消息到队列中可由多个消费者接收;多个消费者之间消息是竞争接收。
-
-
使用Exchange交换机;订阅模式(广播fanout,定向direct,通配符topic)
-
发布与订阅模式:使用了fanout类型的交换机,可以将一个消息发送到所有与交换机绑定的队列并被消费者接收。
-
路由模式:使用了direct类型的交换机,可以将一个消息发送到routing key相关的队列并被消费者接收。
-
通配符模式:使用了topic类型的交换机,可以将一个消息发送到routing key(*,#)相关的队列并被消费者接收。
-

浙公网安备 33010602011771号