小蚁人网站建设,石家庄网站建设远策科技,网站优化目标,我的世界怎么做神器官方网站RabbitMQ的6种工作模式
官方文档#xff1a;
http://www.rabbitmq.com/
https://www.rabbitmq.com/getstarted.html
RabbitMQ 常见的 6 种工作模式#xff1a;
1、simple简单模式 1)、消息产生后将消息放入队列。
2)、消息的消费者监听消息队列#xff0c;如果队列中…RabbitMQ的6种工作模式
官方文档
http://www.rabbitmq.com/
https://www.rabbitmq.com/getstarted.html
RabbitMQ 常见的 6 种工作模式
1、simple简单模式 1)、消息产生后将消息放入队列。
2)、消息的消费者监听消息队列如果队列中有消息就消费掉消息被拿走后自动从队列中删除。
3)、存在的问题消息可能没有被消费者正确处理已经从队列中消失了造成消息的丢失。
4)、应用场景聊天(中间有一个过度的服务器)。
5)、代码实现
pom文件
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.example/groupIdartifactIdrabbitmq-java/artifactIdversion1.0-SNAPSHOT/versiondependenciesdependencygroupIdcom.rabbitmq/groupIdartifactIdamqp-client/artifactIdversion5.10.0/version/dependency/dependencies/project工具类
package com.example;import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;public class ConnectionUtil {// 连接rabbitmq服务共享一个工厂对象private static ConnectionFactory factory;static {factorynew ConnectionFactory();//设置rabbitmq属性factory.setHost(127.0.0.1);factory.setUsername(zsx242030);factory.setPassword(zsx242030);factory.setVirtualHost(/);factory.setPort(5672);}public static Connection getConnection(){Connection connectionnull;try {//获取连接对象connection factory.newConnection();} catch (Exception e) {e.printStackTrace();}return connection;}
}消息提供者
package com.example.simple;import com.example.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;public class Provider {public static void main(String[] args) {try {//获取连接对象Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//通过通道创建队列后续所有的操作都是基于channel实现(队列也可以由消费方创建)channel.queueDeclare(queue1, false, false, false, null);//向队列中发送消息channel.basicPublish(, queue1, null, Hello RabbitMQ!!!.getBytes());//断开连接channel.close();connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者
package com.example.simple;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//监听队列中的消息(消费的是队列而不是交换机)channel.basicConsume(queue1, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态channel.close();connection.close();} catch (Exception e) {e.printStackTrace();}}
}消费者获得消息为Hello RabbitMQ!!!2、work工作模式(资源的竞争) 1)、消息产生者将消息放入队列消费者可以有多个消费者1消费者2同时监听同一个队列。消息被消费
C1 和 C2 共同争抢当前的消息队列内容谁先拿到谁负责消费消息。
2)、存在的问题高并发情况下默认会产生某一个消息被多个消费者共同使用可以设置一个开关
(synchronized与同步锁的性能不一样)保证一条消息只能被一个消费者使用。
3)、应用场景红包大项目中的资源调度(任务分配系统不需知道哪一个任务执行系统在空闲直接将任务扔到
消息队列中空闲的系统自动争抢)对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。
4)、代码实现
消息提供者
package com.example.work;import com.example.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;public class Provider {public static void main(String[] args) {try {//获取连接对象Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//通过通道创建队列channel.queueDeclare(queue1, false, false, false, null);//向队列中发送消息for (int i 1; i 10; i) {channel.basicPublish(, queue1, null, (Hello RabbitMQ!!! i).getBytes());}//断开连接channel.close();connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者1
package com.example.work;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer1 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//监听队列中的消息channel.basicConsume(queue1, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者1获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();// connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者2
package com.example.work;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer2 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//监听队列中的消息channel.basicConsume(queue1, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者2获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();// connection.close();} catch (Exception e) {e.printStackTrace();}}
}消费者1获得消息为Hello RabbitMQ!!!1
消费者1获得消息为Hello RabbitMQ!!!3
消费者1获得消息为Hello RabbitMQ!!!5
消费者1获得消息为Hello RabbitMQ!!!7
消费者1获得消息为Hello RabbitMQ!!!9
消费者2获得消息为Hello RabbitMQ!!!2
消费者2获得消息为Hello RabbitMQ!!!4
消费者2获得消息为Hello RabbitMQ!!!6
消费者2获得消息为Hello RabbitMQ!!!8
消费者2获得消息为Hello RabbitMQ!!!103、publish/subscribe发布订阅(共享资源) 1)、X代表交换机rabbitMQ 内部组件erlang 消息产生者是代码完成代码的执行效率不高消息产生者将消
息放入交换机交换机发布订阅把消息发送到所有消息队列中对应消息队列的消费者拿到消息进行消费。
Exchange 有常见以下 3 种类型 Fanout广播将消息交给所有绑定到交换机的队列。 Direct定向把消息交给符合指定 routing key 的队列。 Topic通配符把消息交给符合 routing pattern (路由模式)的队列。
Exchange (交换机)只负责转发消息不具备存储消息的能力因此如果没有任何队列与 Exchange 绑定或者
没有符合路由规则的队列那么消息会丢失。
2相关场景邮件群发群聊天广播(广告)。
3)、代码实现
消息提供者
package com.example.publishsubscribe;import com.example.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;// 交换机和队列可以在提供方和消费方某一方创建在两边同时创建也可以只要创建的名称一致。
// 保证哪一方先运行则在哪一方创建
public class Provider {public static void main(String[] args) {try {//获取连接对象Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建交换机交换机没有存储数据的能力数据存储在队列上如果有交换机没队列的情况下数据会丢失// 1.参数一交换机名称 参数二交换机类型channel.exchangeDeclare(fanout_exchange, fanout);//通过通道创建队列//channel.queueDeclare(queue1,false,false,false,null);//向队列中发送消息for (int i 1; i 10; i) {channel.basicPublish(fanout_exchange, , null, (Hello RabbitMQ!!! i).getBytes());}//断开连接channel.close();connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者1
package com.example.publishsubscribe;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer1 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建队列channel.queueDeclare(fanout_queue1, false, false, false, null);//给队列绑定交换机channel.queueBind(fanout_queue1, fanout_exchange, );//监听队列中的消息channel.basicConsume(fanout_queue1, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者1获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();//connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者2
package com.example.publishsubscribe;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer2 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建队列channel.queueDeclare(fanout_queue2, false, false, false, null);//给队列绑定交换机channel.queueBind(fanout_queue2, fanout_exchange, );//监听队列中的消息channel.basicConsume(fanout_queue2, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者2获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();//connection.close();} catch (Exception e) {e.printStackTrace();}}
}消费者1获得消息为Hello RabbitMQ!!!1
消费者1获得消息为Hello RabbitMQ!!!2
消费者1获得消息为Hello RabbitMQ!!!3
消费者1获得消息为Hello RabbitMQ!!!4
消费者1获得消息为Hello RabbitMQ!!!5
消费者1获得消息为Hello RabbitMQ!!!6
消费者1获得消息为Hello RabbitMQ!!!7
消费者1获得消息为Hello RabbitMQ!!!8
消费者1获得消息为Hello RabbitMQ!!!9
消费者1获得消息为Hello RabbitMQ!!!10
消费者2获得消息为Hello RabbitMQ!!!1
消费者2获得消息为Hello RabbitMQ!!!2
消费者2获得消息为Hello RabbitMQ!!!3
消费者2获得消息为Hello RabbitMQ!!!4
消费者2获得消息为Hello RabbitMQ!!!5
消费者2获得消息为Hello RabbitMQ!!!6
消费者2获得消息为Hello RabbitMQ!!!7
消费者2获得消息为Hello RabbitMQ!!!8
消费者2获得消息为Hello RabbitMQ!!!9
消费者2获得消息为Hello RabbitMQ!!!104、routing路由模式 1)、消息生产者将消息发送给交换机按照路由判断路由是字符串当前产生的消息携带路由字符交换机根据路
由的 key只能匹配上路由 key 对应的消息队列对应的消费者才能消费消息。队列与交换机的绑定不能是任意
绑定了而是要指定一个 RoutingKey (路由 key)。消息的发送方在向 Exchange 发送消息时也必须指定消息的
RoutingKey 。Exchange 不再把消息交给每一个绑定的队列而是根据消息的 Routing Key 进行判断只有队列
的 Routingkey 与消息的 Routing key 完全一致才会接收到消息。
2)、根据业务功能定义路由字符串。
3)、从系统的代码逻辑中获取对应的功能字符串将消息任务扔到对应的队列中。
4)、业务场景error 通知EXCEPTION错误通知的功能传统意义的错误通知客户通知利用key路由可
以将程序中的错误封装成消息传入到消息队列中开发者可以自定义消费者实时接收错误。
5)、代码实现
消息提供者
package com.example.souting;import com.example.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;// 交换机和队列可以在提供方和消费方某一方创建在两边同时创建也可以只要创建的名称一致。
// 保证哪一方先运行则在哪一方创建public class Provider {public static void main(String[] args) {try {//获取连接对象Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建交换机交换机没有存储数据的能力数据存储在队列上如果有交换机没队列的情况下数据会丢失// 1.参数一交换机名称 参数二交换机类型channel.exchangeDeclare(direct_exchange, direct);//向队列中发送消息for (int i 1; i 10; i) {channel.basicPublish(direct_exchange,//设置路由键符合路由键的队列才能拿到消息insert,null,(Hello RabbitMQ!!! i).getBytes());}//断开连接channel.close();connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者1
package com.example.souting;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer1 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建队列channel.queueDeclare(direct_queue1, false, false, false, null);//绑定交换机routingKey:路由键channel.queueBind(direct_queue1, direct_exchange, select);channel.queueBind(direct_queue1, direct_exchange, insert);//监听队列中的消息channel.basicConsume(direct_queue1, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者1获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();//connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者2
package com.example.souting;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer2 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建队列channel.queueDeclare(direct_queue2, false, false, false, null);//绑定交换机routingKey:路由键channel.queueBind(direct_queue2, direct_exchange, delete);channel.queueBind(direct_queue2, direct_exchange, select);//监听队列中的消息channel.basicConsume(direct_queue2, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者2获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();//connection.close();} catch (Exception e) {e.printStackTrace();}}
}消费者1获得消息为Hello RabbitMQ!!!1
消费者1获得消息为Hello RabbitMQ!!!2
消费者1获得消息为Hello RabbitMQ!!!3
消费者1获得消息为Hello RabbitMQ!!!4
消费者1获得消息为Hello RabbitMQ!!!5
消费者1获得消息为Hello RabbitMQ!!!6
消费者1获得消息为Hello RabbitMQ!!!7
消费者1获得消息为Hello RabbitMQ!!!8
消费者1获得消息为Hello RabbitMQ!!!9
消费者1获得消息为Hello RabbitMQ!!!105、topic 主题模式(路由模式的一种) 1)、Topic 类型与 Direct 相比都是可以根据 RoutingKey 把消息路由到不同的队列。只不过 Topic 类型
Exchange 可以让队列在绑定 Routing key 的时候使用通配符。
2)、Routingkey 一般都是有一个或多个单词组成多个单词之间以 . 分割例如item.insert。
通配符规则
# 匹配一个或多个词
*匹配不多不少恰好1个词
举例
item.# 能够匹配item.insert.abc或者item.insert
item.* 只能匹配 item.insert
usa.# 因此凡是以 usa. 开头的 routing key 都会被匹配到
#.news 因此凡是以 .news 结尾的 routing key 都会被匹配
3)、路由功能添加模糊匹配。
4)、消息产生者产生消息把消息交给交换机。
5)、交换机根据key的规则模糊匹配到对应的队列由队列的监听消费者接收消息消费。
6)、代码实现
消息提供者
package com.example.topic;import com.example.ConnectionUtil;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;//交换机和队列可以在提供方和消费方某一方创建在两边同时创建也可以只要创建的名称一致。
// 保证哪一方先运行则在哪一方创建public class Provider {public static void main(String[] args) {try {//获取连接对象Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建交换机交换机没有存储数据的能力数据存储在队列上如果有交换机没队列的情况下数据会丢失 //1.参数一交换机名称 参数二交换机类型channel.exchangeDeclare(topic_exchange, topic);//向队列中发送消息for (int i 1; i 10; i) {channel.basicPublish(topic_exchange,// #:匹配0-n个单词(之间以.区分,两点之间算一个单词可以匹配hello world空格的情况) *(匹配一个单词)emp.hello world,null,(Hello RabbitMQ!!! i).getBytes());}//断开连接channel.close();connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者1
package com.example.topic;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer1 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建队列channel.queueDeclare(topic_queue1, false, false, false, null);//绑定交换机routingKey:路由键 #匹配0-n个单词之间以.区分两点之间算一个单词channel.queueBind(topic_queue1, topic_exchange, emp.#);//监听队列中的消息channel.basicConsume(topic_queue1, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者1获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();//connection.close();} catch (Exception e) {e.printStackTrace();}}
}消息消费者2
package com.example.topic;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Consumer2 {public static void main(String[] args) {try {Connection connection ConnectionUtil.getConnection();//获取通道对象Channel channel connection.createChannel();//创建队列channel.queueDeclare(topic_queue2, false, false, false, null);//绑定交换机routingKey:路由键 *匹配1个单词之间以.区分两点之间算一个单词channel.queueBind(topic_queue2, topic_exchange, emp.*);//监听队列中的消息channel.basicConsume(topic_queue2, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {System.out.println(消费者2获得消息为 new String(body, utf-8));}});//消费方不需要关闭连接保持一直监听队列状态// channel.close();//connection.close();} catch (Exception e) {e.printStackTrace();}}
}消费者1获得消息为Hello RabbitMQ!!!1
消费者1获得消息为Hello RabbitMQ!!!2
消费者1获得消息为Hello RabbitMQ!!!3
消费者1获得消息为Hello RabbitMQ!!!4
消费者1获得消息为Hello RabbitMQ!!!5
消费者1获得消息为Hello RabbitMQ!!!6
消费者1获得消息为Hello RabbitMQ!!!7
消费者1获得消息为Hello RabbitMQ!!!8
消费者1获得消息为Hello RabbitMQ!!!9
消费者1获得消息为Hello RabbitMQ!!!106、RPC RPC即客户端远程调用服务端的方法 使用MQ可以实现RPC的异步调用基于Direct交换机实现流程如下
1)、客户端即是生产者也是消费者向RPC请求队列发送RPC调用消息同时监听RPC响应队列。
2)、服务端监听RPC请求队列的消息收到消息后执行服务端的方法得到方法返回的结果。
3)、服务端将RPC方法 的结果发送到RPC响应队列。
4)、客户端(RPC调用方)监听RPC响应队列接收到RPC调用结果。
5)、代码实现
Client端
package com.example.rpc;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;public class Client {public static void main(String[] argv) throws IOException, InterruptedException {String message Hello World!!!;// 建立一个连接和一个通道并为回调声明一个唯一的回调队列Connection connection ConnectionUtil.getConnection();Channel channel connection.createChannel();// 定义一个临时变量的接受队列名String replyQueueName channel.queueDeclare().getQueue();// 生成一个唯一的字符串作为回调队列的编号String corrId UUID.randomUUID().toString();// 发送请求消息消息使用了两个属性replyTo和correlationId// 服务端根据replyTo返回结果客户端根据correlationId判断响应是不是给自己的AMQP.BasicProperties props new AMQP.BasicProperties.Builder().correlationId(corrId).replyTo(replyQueueName).build();// 发布一个消息rpc_queue路由规则channel.basicPublish(, rpc_queue, props, message.getBytes(UTF-8));// 由于我们的消费者交易处理是在单独的线程中进行的因此我们需要在响应到达之前暂停主线程。// 这里我们创建的容量为1的阻塞队列ArrayBlockingQueue因为我们只需要等待一个响应。final BlockingQueueString response new ArrayBlockingQueueString(1);// String basicConsume(String queue, boolean autoAck, Consumer callback)channel.basicConsume(replyQueueName, true, new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body) throws IOException {//检查它的correlationId是否是我们所要找的那个if (properties.getCorrelationId().equals(corrId)) {//如果是则响应BlockingQueueresponse.offer(new String(body, UTF-8));}}});System.out.println( 客户端请求的结果 response.take());}
}Server端
package com.example.rpc;import com.example.ConnectionUtil;
import com.rabbitmq.client.*;import java.io.IOException;public class Server {public static void main(String[] args) {Connection connection null;try {connection ConnectionUtil.getConnection();Channel channel connection.createChannel();channel.queueDeclare(rpc_queue, false, false, false, null);channel.basicQos(1);System.out.println(Awaiting RPC requests);Consumer consumer new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,byte[] body) throws IOException {AMQP.BasicProperties replyProps new AMQP.BasicProperties.Builder().correlationId(properties.getCorrelationId()).build();String response ;try {response new String(body, UTF-8);System.out.println(response ( response ));} catch (RuntimeException e) {System.out.println(错误信息 e.toString());} finally {// 返回处理结果队列channel.basicPublish(, properties.getReplyTo(), replyProps, response.getBytes(UTF-8));// 确认消息已经收到后面参数 multiple是否批量.true:将一次性确认所有小于envelope.getDeliveryTag()的消息。channel.basicAck(envelope.getDeliveryTag(), false);// RabbitMq consumer worker thread notifies the RPC// server owner threadsynchronized (this) {this.notify();}}}};// 取消自动确认boolean autoAck false;channel.basicConsume(rpc_queue, autoAck, consumer);// Wait and be prepared to consume the message from RPC client.while (true) {synchronized (consumer) {try {consumer.wait();} catch (InterruptedException e) {e.printStackTrace();}}}} catch (Exception e) {e.printStackTrace();} finally {try {connection.close();} catch (IOException e) {e.printStackTrace();}}}
}Awaiting RPC requests
response (Hello World!!!)
response (Hello World!!!)
response (Hello World!!!)# 客戶端发起3次请求
客户端请求的结果Hello World!!!
客户端请求的结果Hello World!!!
客户端请求的结果Hello World!!!7、发布订阅模式与工作队列模式的区别
1、工作队列模式不用定义交换机而发布/订阅模式需要定义交换机。
2、发布/订阅模式的生产方是面向交换机发送消息工作队列模式的生产方是面向队列发送消息(底层使
用默认交换机)。
3、发布/订阅模式需要设置队列和交换机的绑定工作队列模式不需要设置实际上工作队列模式会将
队列绑定到默认的交换机 。