04. RabbitMQ的几种工作模式
🍎姓名:程序员阿红🍎
🍊喜欢:Java编程🍊
🍉重要的事情说三遍!!!🍉
🍓欢迎大家关注哦,互相学习🍓
🍋欢迎大家访问哦,互相学习🍋
🍑欢迎大家收藏哦,互相学习🍑
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
🍟🍟🍟RabbitMQ提供了6种消息模型,但是第6种其实是RPC,并不是MQ,因此我们只学习前5种
🍗🍗🍗在线手册:https://www.rabbitmq.com/getstarted.htm
5种消息模型,大体分为两类:
- 1和2属于点对点
- 3、4、5属于发布订阅模式(一对多)
1. 模式概括
1.1 点对点模式:
P2P(point to point)模式包含三个角色:
- 消息队列(queue),生产者(sender),消费者(receiver)
- 每个消息发送到一个特定的队列中,消费者从中获得消息
- 队列中保留这些消息,直到他们被消费或超时
- 特点:
- 每个消息只有一个消费者,一旦消费,消息就不在队列中了。2. 生产者和消费者之间没有依赖性,生产者只管生产消息,消费者只能消费消息。
- 接收者成功接收消息之后需向对象应答成功(确认|ACK机制)
- 如果希望发送的每个消息都会被成功处理,那需要P2P
1.2 发布订阅模式:
publish(Pub)/subscribe(Sub):
- pub/sub模式包含三个角色:交换机(exchange),发布者(publisher),订阅者 (subcriber)(没有队列是因为,队列只需要在消费者绑定路由即可)
- 多个发布者将消息发送交换机,系统将这些消息传递给多个订阅者
- 特点:
- 每个消息可以有多个订阅者2. 发布者和订阅者之间在时间上有依赖,对于某个交换机的订阅者,必须创建一个订阅 后,才能消费发布者的消息
- 为了消费消息,订阅者必须保持运行状态;2. 如果希望发送的消息被多个消费者处理,可采用本模式
2. 模式分类
2.1点对点模式-简单模式
下面引用官网的一段介绍:
Introduction
RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as
a post office: when you put the mail that you want posting in a post box, you can be sure
that Mr. or Ms. Mailperson will eventually deliver the mail to your recipient. In this analogy,
RabbitMQ is a post box, a post office and a postman.
译文:RabbitMQ是一个消息代理:它接收和转发消息。你可以把它想象成一个邮局:当你把你想要
寄的邮件放到一个邮箱里,你可以确定邮递员先生或女士最终会把邮件送到你的收件人那里。在
这个类比中,RabbitMQ是一个邮箱、一个邮局和一个邮递员。
RabbitMQ本身只是接收,存储和转发消息,并不会对信息进行处理!
类似邮局,处理信件的应该是收件人而不是邮局!
- RabbitMQ本身只是接收,存储和转发消息,并不会对信息进行处理!
- 类似邮局,处理信件的应该是收件人而不是邮局!
生产者代码:
package simplemode;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import util.ConnectionUtil;/**
* @author WeiHong
* @date 2021 - 09 - 06 16:39
* 简单模式
* 消息生产者
*/publicclassSender{publicstaticvoidmain(String[] args)throws Exception {
String msg ="学习rabbitMQ,ACK手动确认!";//1.获取连接
Connection connection = ConnectionUtil.getConnection();//2.在连接中创建通道
Channel channel = connection.createChannel();//3.创建消息队列(1、2、3、4、5)/**
* 参数1:队列的名称
* 参数2:队列中的数据是否持久化
* 参数3:是否排外(是否支持扩展,当前队列只能自己用,不能给别人用)
* 参数4:是否自动删除(当队列连接数为0时,队列会销毁,不管队列是否存有保存数据)
* 参数5:队列参数(没有参数为null)
*/
channel.queueDeclare("queue1",false,false,false,null);//4.向指定的队列发送消息/**
* 参数1:交换机名称,当前为简单模式,也就是p2p模式,没有交换机,所以名称为“”;
* 参数2:目标队列的名称
* 参数3:设置消息的属性(没有属性则为null)
* 参数4:消息的内容(只接收字节数组)
*/
channel.basicPublish("","queue1",null,msg.getBytes());
System.out.println("发送:"+msg);//5.释放资源
channel.close();
connection.close();}}
启动生产者,即可前往管理端查看队列中的信息,会有一条信息没有处理和确认
消费者代码:
package simplemode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 06 17:00
* 消息接收者
*/publicclassRecer{publicstaticvoidmain(String[] args)throws Exception{// 1.获取连接
Connection connection = ConnectionUtil.getConnection();// 2.在连接中创建通道(信道)
Channel channel = connection.createChannel();// 3.从信道中获得信息
DefaultConsumer consumer =newDefaultConsumer(channel){@Override//交付处理(收件人信息,信封(包裹上的快递标签),协议的配置,消息)publicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {//body就是从队列中获取的消息
String s=newString(body);
System.out.println("接收="+s);}};// 4.监听队列 true:自动消息确认
channel.basicConsume("queue1",true,consumer);}}
启动消费者,前往管理端查看队列中的信息,所有信息都已经处理和确认,显示0
消息确认机制ACK:
- 通过刚才的案例可以看出,消息一旦被消费,消息就会立刻从队列中移除
- RabbitMQ如何得知消息被消费者接收?
- 如果消费者接收消息后,还没执行操作就抛异常宕机导致消费失败,但是RabbitMQ无从得知,这样消息就丢失了2. 因此,RabbitMQ有一个ACK机制,当消费者获取消息后,会向RabbitMQ发送回执ACK,告知消息已经被接收
- ACK:(Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接收无误我们在使用http请求时,http的状态码200就是告诉我们服务器执行成功2. 整个过程就想快递员将包裹送到你手里,并且需要你的签字,并拍照回执
- 不过这种回执ACK分为两种情况:
- 自动ACK:消息接收后,消费者立刻自动发送ACK(快递放在快递柜)2. 手动ACK:消息接收后,不会发送ACK,需要手动调用(快递必须本人签收)
- 两种情况如何选择,需要看消息的重要性:
- 如果消息不太重要,丢失也没有影响,自动ACK会比较方便2. 如果消息非常重要,最好消费完成手动ACK,如果自动ACK消费后,RabbitMQ就会把
- 消息从队列中删除,如果此时消费者抛异常宕机,那么消息就永久丢失了
- 修改手动消息确认
// 4.监听队列 false:手动消息确认
channel.basicConsume("queue1",false,consumer);
- 结果如下
确认ACK代码如下:
package simplemode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @BelongsProject: lagou-rabbitmq
* @Author: GuoAn.Sun
* @CreateTime: 2020-08-10 15:08
* @Description: 消息接收者,加入ACK确认机制
*/publicclassRecerByACK{publicstaticvoidmain(String[] args)throws Exception {// 1.获得连接
Connection connection = ConnectionUtil.getConnection();// 2.获得通道(信道)final Channel channel = connection.createChannel();// 3.从信道中获得消息
DefaultConsumer consumer =newDefaultConsumer(channel){@Override//交付处理(收件人信息,包裹上的快递标签,协议的配置,消息)publicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {// body就是从队列中获取的消息
String s =newString(body);
System.out.println("接收 = "+ s);// 手动确认(收件人信息,是否同时确认多个消息)
channel.basicAck(envelope.getDeliveryTag(),false);}};// 4.监听队列 false:手动消息确认
channel.basicConsume("queue1",false,consumer);}}
ACK确认模式:
// 4.监听队列 false:手动消息确认,必须为手动消息确认,ACK确认机制才生效。*
*channel.basicConsume(“queue1”,fasle,consumer);
没执行channel.basicAck(envelope.getDeliveryTag(),false);该语句时消息是未被确认的。
2.2 工作队列模式
- 之前我们学习的简单模式,一个消费者来处理消息,如果生产者生产消息过快过多,而消费者的能力有限,就会产生消息在队列中堆积(生活中的滞销)
- 一个烧烤师傅,一次烤50支羊肉串,就一个人吃的话,烤好的肉串会越来越多,怎么处理?
- 多招揽客人进行消费即可。当我们运行许多消费者程序时,消息队列中的任务会被众多消费者共享,但其中某一个消息只会被一个消费者获取(100支肉串20个人吃,但是其中的某支肉串只能被一个人吃)
生产者代码:
package workmode;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import util.ConnectionUtil;/**
* @author WeiHong
* @date 2021 - 09 - 06 19:23
* 工作模型
*/publicclassSender{publicstaticvoidmain(String[] args)throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.queueDeclare("work_queue",false,false,false,null);for(int i =1;i<=100;i++){
String msg ="羊肉串 --> "+ i;
channel.basicPublish("","work_queue", null, msg.getBytes());
System.out.println("新鲜出炉:"+ msg);}
channel.close();
connection.close();}}
消费者1代码:
package workmode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 06 21:22
*/publicclassRecer1{staticint i =1;publicstaticvoidmain(String[] args)throws Exception{
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();//声明队列、双重含义// 如果队列不存在,就创建;如果队列存在,则获取
channel.queueDeclare("work_queue",false,false,false,null);
channel.basicQos(1);//系统不会给消费者发送超过1个消息以上,只有确认ACK后,才回继续发下一个消息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {//body就是从队列中获取的消息
String s=newString(body);
System.out.println("【顾客1】吃掉 "+ s+" ! 总共吃【"+i+++"】串!"+"信封收件人:"+envelope.getDeliveryTag());//模拟网络延迟try{
Thread.sleep(200);}catch(Exception e){
e.printStackTrace();}//手动确认(收件人信息,是否确认多个消息)
channel.basicAck(envelope.getDeliveryTag(),false);}};// 4.监听队列 false:手动消息确认
channel.basicConsume("work_queue",false,consumer);}}
消费者2代码:
package workmode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @BelongsProject: lagou-rabbitmq
* @Author: GuoAn.Sun
* @CreateTime: 2020-08-10 15:08
* @Description: 消息接收者,加入ACK确认机制
*/publicclassRecer2{staticint i =1;publicstaticvoidmain(String[] args)throws Exception {// 1.获得连接
Connection connection = ConnectionUtil.getConnection();// 2.获得通道(信道)final Channel channel = connection.createChannel();
channel.queueDeclare("work_queue",false,false,false,null);
channel.basicQos(1);// 3.从信道中获得消息
DefaultConsumer consumer =newDefaultConsumer(channel){@Override//交付处理(收件人信息,包裹上的快递标签,协议的配置,消息)publicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String s =newString(body);
System.out.println("【顾客2】吃掉 "+ s+" ! 总共吃【"+i+++"】串!");// 模拟网络延迟try{
Thread.sleep(900);}catch(Exception e){}// 手动确认(收件人信息,是否同时确认多个消息)
channel.basicAck(envelope.getDeliveryTag(),false);}};// 4.监听队列 false:手动消息确认
channel.basicConsume("work_queue",false,consumer);}}
结果:
生产者产生100个羊肉串
消费者1消费了81条消息
消费者2消费了19条消息
channel.basicQos:系统不会给消费者发送超过1个消息以上,只有确认ACK后,才回继续发下一个消息
- 不加channel.basicQos(1);
- 不加channel.basicQos(1),消费者是相互竞争的关系,但是会把消息进行平分。
- 例:1个生产者;2个消费者。生产者发送100条信息,消费者尽管消费速度不一样,这两个消费者还是会将这100条数据各分50条。
- 加channel.basicQos(1);
- 遵循能者多劳机制,消费者是相互竞争的关系,但是不会把消息进行平分。消费速度快的会继续消费信息,直至所有消息被消费完。
能者多劳必须要配合手动的ACK机制才生效:
- 面试题:避免消息堆积?
- workqueue,多个消费者监听同一个队列
- 接收到消息后,通过线程池,异步消费
2.3 发布订阅模式
发布-订阅
在上一篇教程中,我们创建了一个工作队列。工作队列背后的假设是,每个任务都被准确地交
付给一个工作者。在这一部分中,我们将做一些完全不同的事情——将消息传递给多个消费者。
此模式称为“发布/订阅”。
为了演示这个模式,我们将构建一个简单的日志记录系统。它将由两个程序组成——第一个将
发送日志消息,第二个将接收和打印它们。
在我们的日志系统中,接收程序的每一个正在运行的副本都将获得消息。这样我们就可以运行
一个接收器并将日志指向磁盘;与此同时,我们可以运行另一个接收器并在屏幕上看到日志。
基本上,发布的日志消息将广播到所有接收方
生活中的案例:就是玩抖音快手,众多粉丝关注一个视频主,视频主发布视频,所有粉丝都可以得到视
频通知
上图中,X就是视频主,红色的队列就是粉丝。binding是绑定的意思(关注)
P生产者发送信息给X路由,X将信息转发给绑定X的队列
X队列将信息通过信道发送给消费者,从而进行消费
整个过程,必须先创建路由
路由在生产者程序中创建
因为路由没有存储消息的能力,当生产者将信息发送给路由后,消费者还没有运行,所以没
有队列,路由并不知道将信息发送给谁
运行程序的顺序:
1.先运行生产者sender;创建路由
2在运行消费者Recer1、Recer2。
生产者代码
package publishSubscribeMode;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import util.ConnectionUtil;/**
* @author WeiHong
* @date 2021 - 09 - 07 14:11
* 发布订阅模式
*/publicclassSender{publicstaticvoidmain(String[] args)throws Exception {// 1.获取连接
Connection connection = ConnectionUtil.getConnection();// 2.在连接中创建信道
Channel channel = connection.createChannel();// 3.声明路由(4种路由)// fanout:不处理路由键(只需要将队列绑定到路由上,发送到路由的消息都会被转发到与该路由绑定的所有队列上)
channel.exchangeDeclare("test_exchange_fanout","fanout");// 4.发布消息
String msg ="这是发布订阅模式的fanout路由模型的消息";
channel.basicPublish("test_exchange_fanout","",null,msg.getBytes());
System.out.println("发送:"+msg);// 5.释放资源
channel.close();
connection.close();}}
消费者1代码
package publishSubscribeMode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 07 15:29
* 发布订阅模式-消费者1
*/publicclassRecer1{publicstaticvoidmain(String[] args)throws Exception{// 1.获取连接
Connection connection = ConnectionUtil.getConnection();// 2.在链接中创建信道
Channel channel = connection.createChannel();//2.1声明队列
channel.queueDeclare("test_exchange_fanout_queue1",false,false,false,null);//2.2绑定路由
channel.queueBind("test_exchange_fanout_queue1","test_exchange_fanout","");// 3.定义内部类重写方法接收消息\从信道中获得信息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String s =newString(body);
System.out.println("[消费者1] = "+ s);}};// 4.监听队列 true:自动消息确认
channel.basicConsume("test_exchange_fanout_queue1",true,consumer);}}
消费者2代码
package publishSubscribeMode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 07 15:29
* 发布订阅模式-消费者2
*/publicclassRecer2{publicstaticvoidmain(String[] args)throws Exception{// 1.获取连接
Connection connection = ConnectionUtil.getConnection();// 2.在链接中创建信道
Channel channel = connection.createChannel();//2.1声明队列
channel.queueDeclare("test_exchange_fanout_queue2",false,false,false,null);//2.2绑定路由
channel.queueBind("test_exchange_fanout_queue2","test_exchange_fanout","");// 3.定义内部类重写方法接收消息\从信道中获得信息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String s =newString(body);
System.out.println("[消费者2] = "+ s);}};// 4.监听队列 true:自动消息确认
channel.basicConsume("test_exchange_fanout_queue2",true,consumer);}}
2.4 路由模式
- 路由会根据类型进行定向分发消息给不同的队列,如图所示
生产者代码
package routerMode;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import util.ConnectionUtil;/**
* @author WeiHong
* @date 2021 - 09 - 09 14:38
* 路由模式-生产者
* 路由会根据类型进行定向分发消息给不同的队列
*/publicclassSender{publicstaticvoidmain(String[] args)throws Exception {//1.获取连接
Connection connection = ConnectionUtil.getConnection();//2.在连接中创建信道
Channel channel = connection.createChannel();//3.路由声明(路由名,路由类型)//direct:会根据路由键进行定向分发消息
channel.exchangeDeclare("router_exchange_direct","direct");//4.向队列发送信息for(int i =0; i <10; i++){
String msg ="查询的数据第"+i+"条消息!";//selecte:此时该参数为路由键不是队列名
channel.basicPublish("router_exchange_direct","selecte",null,msg.getBytes());
System.out.println("生产者发送="+msg);}//5.释放连接
channel.close();
connection.close();}}
消费者1代码
package routerMode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 09 15:05
*/publicclassRecer1{publicstaticvoidmain(String[] args)throws Exception {//1.获取连接
Connection connection = ConnectionUtil.getConnection();//2.在链接中创建信道
Channel channel = connection.createChannel();//2.1声明队列
channel.queueDeclare("exchange_direct_queue1",false,false,false,null);//2.2绑定路由(如果路由键的类型是插入、修改绑定到这个队列1上)
channel.queueBind("exchange_direct_queue1","router_exchange_direct","insert");
channel.queueBind("exchange_direct_queue1","router_exchange_direct","update");//3.定义内部类获取信息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String res =newString(body);
System.out.println("【消费者1】="+ res);}};//4.监听队列 true:自动消息确认
channel.basicConsume("exchange_direct_queue1",true,consumer);}}
消费者2代码
package routerMode;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 09 15:05
*/publicclassRecer2{publicstaticvoidmain(String[] args)throws Exception {//1.获取连接
Connection connection = ConnectionUtil.getConnection();//2.在链接中创建信道
Channel channel = connection.createChannel();//2.1声明队列
channel.queueDeclare("exchange_direct_queue2",false,false,false,null);//2.2绑定路由(如果路由键的类型是查询绑定到这个队列2上)
channel.queueBind("exchange_direct_queue2","router_exchange_direct","selecte");//3.定义内部类获取信息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String res =newString(body);
System.out.println("【消费者2】="+ res);}};//4.监听队列 true:自动消息确认
channel.basicConsume("exchange_direct_queue2",true,consumer);}}
运行顺序
- 记住运行程序的顺序,先运行一次sender(创建路由器),
- 有了路由器之后,在创建两个Recer1和Recer2,进行队列绑定
- 再次运行sender,发出消息
消费者接收信息由路由键确定,当生产者发送信息到路由上时,因为指定了路由键,所以消息会被指派到对应的消息队列里。消费者通过队列绑定路由接收到不同路由键的消息。
//selecte:此时该参数为路由键不是队列名
channel.basicPublish("router_exchange_direct","selecte",null,msg.getBytes());//2.2绑定路由(如果路由键的类型是查询绑定到这个队列2上)
channel.queueBind("exchange_direct_queue2","router_exchange_direct","selecte");
2.5 通配符模式
和路由模式90%是一样的。
唯独的区别就是路由键支持模糊匹配
匹配符号
*:只能匹配一个词(正好一个词,多一个不行,少一个也不行)
#:匹配0个或更多个词
看一下官网案例:
Q1绑定了路由键 .orange. Q2绑定了路由键 ..rabbit 和 lazy.#
下面生产者的消息会被发送给哪个队列?
quick.orange.rabbit # Q1 Q2
lazy.orange.elephant # Q1 Q2
quick.orange.fox # Q1
lazy.brown.fox # Q2
lazy.pink.rabbit # Q2
quick.brown.fox # 无
orange # 无
quick.orange.male.rabbit # 无
生产者代码
package topic;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import util.ConnectionUtil;/**
* @author WeiHong
* @date 2021 - 09 - 14 14:03
*/publicclassSender{publicstaticvoidmain(String[] args)throws Exception {
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();// 声明路由(路由名,路由类型)// topic:模糊匹配的定向分发
channel.exchangeDeclare("test_exchange_topic","topic");
String msg ="商品降价";
channel.basicPublish("test_exchange_topic","produce.price.test", null,
msg.getBytes());
System.out.println("[用户系统]:"+ msg);
channel.close();
connection.close();}}
消费者1代码
package topic;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 14 14:10
*/publicclassRecer1{publicstaticvoidmain(String[] args)throws Exception {//1.建立连接
Connection connection = ConnectionUtil.getConnection();//2.在链接中建立信道
Channel channel = connection.createChannel();//3.声明队列
channel.queueDeclare("test_exchange_topic_queue1",false,false,false,null);//4.绑定路由
channel.queueBind("test_exchange_topic_queue1","test_exchange_topic","user.*");//5.定义内部类接收消息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String msg =newString(body);
System.out.println("[消费者1]接收到的信息:"+msg);}};//6.监听队列 true:消息自动确认
channel.basicConsume("test_exchange_topic_queue1",true,consumer);}}
消费者2代码
package topic;import com.rabbitmq.client.*;import util.ConnectionUtil;import java.io.IOException;/**
* @author WeiHong
* @date 2021 - 09 - 14 14:10
*/publicclassRecer2{publicstaticvoidmain(String[] args)throws Exception {//1.建立连接
Connection connection = ConnectionUtil.getConnection();//2.在链接中建立信道
Channel channel = connection.createChannel();//3.声明队列
channel.queueDeclare("test_exchange_topic_queue2",false,false,false,null);//4.绑定路由
channel.queueBind("test_exchange_topic_queue2","test_exchange_topic","produce.#");//5.定义内部类接收消息
DefaultConsumer consumer =newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body)throws IOException {
String msg =newString(body);
System.out.println("[消费者2]接收到的信息:"+msg);}};//6.监听队列 true:消息自动确认
channel.basicConsume("test_exchange_topic_queue2",true,consumer);}}
几种常见路由件说明:
- 发布/订阅模式
*// fanout:不处理路由键(只需要将队列绑定到路由上,发送到路由的消息都会被转发到与该路由绑定的所有队列上)
*channel.exchangeDeclare(“test_exchange_fanout”,“fanout”);
- 路由模式
*//direct:会根据路由键进行定向分发消息
*channel.exchangeDeclare(“router_exchange_direct”,“direct”);
- 通配符模式
*// topic:模糊匹配的定向分发
*channel.exchangeDeclare(“test_exchange_topic”, “topic”);
🍎姓名:程序员阿红🍎
🍊喜欢:Java编程🍊
🍉重要的事情说三遍!!!🍉
🍓欢迎大家关注哦,互相学习🍓
🍋欢迎大家访问哦,互相学习🍋
🍑欢迎大家收藏哦,互相学习🍑
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
版权归原作者 程序员阿红 所有, 如有侵权,请联系我们删除。