1.RabbitMQ之工作模式简介
RabbitMQ的工作模式指的就是在实际缓存消息过程中实现的流程。
RabbitQM官网提供了六种工作模式:
1、Hello Word 简单工作模式
2、Work queues 工作队列模式
3、Publish/Subscribe 发布与订阅模式
4、Routing 路由模式
5、Topics 主题模式
6、RPC 远程调用模式
由于RPC远程调用,不太算 MQ;这里暂不作介绍
2.RabbitMQ工作模式中的相关概念
对于入门RabbitMQ的读者来说,RabbitMQ的相关概念可能晦涩难懂,如果想彻底理解可以结合后面对工作模式的详解中的代码和RabbitMQ 基础架构图来理解。
RabbitMQ 基础架构如下图:
RabbitMQ 中的相关概念:
1、Messag消息,消息是不具体的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-mode(指出该消息可能需要持久性存储)等。
2、Publisher 消息的生产者,也是一个向交换器发布消息的客户端应用程序。
3、Exchang交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
4、Bindin绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。
5、Queu消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
6、Connection 网络连接,比如一个TCP连接。
7、Channe 信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内地虚拟连接,AMQP命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TC都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接。
8、Consume 消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
9、Virtual Ho虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加密环境的独立服务器域。每个 vhost 本质上就是一min版的 RabbitMQ 服务器,拥有自己的队列、交换器、绑定和权限机制。vhost 是 AMQ概念的基础,必须在连接时指定,RabbitM 默认的 vhost 是 / 。
10、Broker 表示消息队列服务器实体
介绍完基础概念,下面上代码,让我们根据代码更加深入的理解RabbitMQ的工作模式
Hello Word 简单工作模式
1.在相关文件夹下面新建两个Maven项目(消费者和生产者)
producr:生产者,相当于发送消息的一方
consumer:消费者,相当于接收消息的一方
2.在pom.xml中导入spring集成RabbitMQ的jar
<!-- rabbit客户端依赖-->
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
3.编写producer端代码发送消息
在producre项目下的com.xxx.rabbitMQ包下建立 Producer_HelloWorld 类
/**
* 简单模式:发送消息
* 1.创建连接工厂
* 2.设置参数
* 3.创建连接Connection
* 4.创建Channel
* 5.创建队列Queue
* 6.发送消息
*/
public class Producer_HelloWorld {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2. 设置参数
factory.setHost("RubbitMQ安装的主机ip地址");//ip 默认值 localhost
factory.setPort(5672); //端口 默认值 5672
factory.setVirtualHost("/");//虚拟机 默认值/
factory.setUsername("guest");//用户名 默认 guest
factory.setPassword("guest");//密码 默认值 guest
//3. 创建连接 Connection
Connection connection = factory.newConnection();
//4. 创建Channel
Channel channel = connection.createChannel();
//5. 创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
参数:
1. queue:队列名称
2. durable:是否持久化,当mq重启之后,还在
3. exclusive:
* 是否独占。只能有一个消费者监听这队列
* 当Connection关闭时,是否删除队列
*
4. autoDelete:是否自动删除。当没有Consumer时,自动删除掉
5. arguments:参数。
*/
//如果没有一个名字叫hello_world的队列,则会创建该队列,如果有则不会创建
channel.queueDeclare("hello_world",true,false,false,null);
/*
basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body)
参数:
1. exchange:交换机名称。简单模式下交换机会使用默认的 ""
2. routingKey:路由名称
3. props:配置信息
4. body:发送消息数据
*/
String body = "hello rabbitmq~~~";
//6. 发送消息
channel.basicPublish("","hello_world",null,body.getBytes());
//7.释放资源
channel.close();
connection.close();
}
}
4.编consumer端代码发送消息
consumer项目下的com.xxx.rabbitMQ包下建立Consumerr_HelloWorld 类
public class Consumer_HelloWorld {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2. 设置参数
factory.setHost("192.168.43.137");//ip 默认值 localhost
factory.setPort(5672); //端口 默认值 5672
factory.setVirtualHost("/");//虚拟机 默认值/
factory.setUsername("guest");//用户名 默认 guest
factory.setPassword("guest");//密码 默认值 guest
//3. 创建连接 Connection
Connection connection = factory.newConnection();
//4. 创建Channel
Channel channel = connection.createChannel();
//5. 创建队列Queue
/*
queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments)
参数:
1. queue:队列名称
2. durable:是否持久化,当mq重启之后,还在
3. exclusive:
* 是否独占。只能有一个消费者监听这队列
* 当Connection关闭时,是否删除队列
*
4. autoDelete:是否自动删除。当没有Consumer时,自动删除掉
5. arguments:参数。
*/
//如果没有一个名字叫hello_world的队列,则会创建该队列,如果有则不会创建
channel.queueDeclare("hello_world",true,false,false,null);
/*
basicConsume(String queue, boolean autoAck, Consumer callback)
参数:
1. queue:队列名称
2. autoAck:是否自动确认
3. callback:回调对象
*/
// 接收消息 匿名内部类
Consumer consumer = new DefaultConsumer(channel){
/*
回调方法,当收到消息后,会自动执行该方法
1. consumerTag:标识
2. envelope:获取一些信息,交换机,路由key...
3. properties:配置信息
4. body:数据
*/
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
System.out.println("consumerTag:"+consumerTag);
System.out.println("Exchange:"+envelope.getExchange());
System.out.println("RoutingKey:"+envelope.getRoutingKey());
System.out.println("properties:"+properties);
System.out.println("body:"+new String(body));
}
};
//接收消息
channel.basicConsume("hello_world",true,consumer);
//关闭资源?不要
}
}
5.启动服务观察打印结果
启动自己安装的RibbitMQ服务,再分别运行Producre和Consumer的相关类发送和接收消息,在RibbiMQ的管理界面就可以看到相应的服务和idea控制台打印的消息
Work queues 工作队列模式
work queres不用自动声明交换机,但是它会调用默认的交换机,该工作模式采用的是在生产者端创建多个队列queue,然后生产者端将消息品军储存在每个队列中。来到消费者端,消费者端通过创建connection连接,然后绑定生产者创建的队列,接收相应队列中的消息。
⚫ Work Queues:与入门程序的简单模式相比,多了一个或一些消费端,多个消费端共同消费同一个队列中的消息。
⚫ 应用场景:对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。
1.在相关文件夹下面新建两个Maven项目(消费者和生产者)
producr:生产者,相当于发送消息的一方
consumer:消费者,相当于接收消息的一方
2.在pom.xml中导入spring集成RabbitMQ的jar
<!-- rabbit客户端依赖-->
<dependencies>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.6.0</version>
</dependency>
</dependencies>
3.编写producer端代码发送消息
在producre项目下的com.xxx.rabbitMQ包下建立 Producer_WorkQueues 类
/**
* 工作模式:发送消息
*/
public class Producer_WorkQueues {
public static void main(String[] args) throws IOException, TimeoutException {
//1.创建连接工厂
ConnectionFactory factory = new ConnectionFactory();
//2. 设置参数
factory.setHost("192.168.43.137");//ip 默认值 localhost
factory.setPort(5672); //端口 默认值 5672
factory.setVirtualHost("/");//虚拟机 默认值/
factory.setUsername("guest");//用户名 默认 guest
f