RabbitMQ 其实一共有六种工作模式:
java
简单模式(Simple)、工作队列模式(Work Queue)、
发布订阅模式(Publish/Subscribe)、路由模式(Routing)、通配符模式(Topic)、
远程调用模式(RPC)。
其中发布订阅模式、路由模式、通配符模式这三种模型都属于订阅模式,只不过它们之间进行路由的方式不同罢了。
远程调用模式是RPC不属于MQ,所以最终统计下来就是五种工作模式。
总结:简单模式和工作队列模式,主要是【队列】和【消费者】的关系,一对一、一对多。
订阅模式包含:【交换机】和【队列】的关系,【队列】和【消费者】的关系。
队列和消费者是1对多时,那么就是采用平均的方式分给多个消费。队列里面的消息只有一个消费者会拿到。
一、简单模式(Simple)
【队列】和【消费者】
二、工作队列模式
java
工作队列模式(Work Queue)多了一些消费者,该模式也使用direct交换机,应用于处理消息较多的情况。
特点: 一个队列对应多个消费者,通过队列进行消息传递 一条消息只会被一个消费者消费,
消息队列默认采用轮询的方式将消息平均发送给消费者,使用Rabbitmq默认交换机direct
应用场景: 对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。
java
缺点:因为消息是轮询平均发送给消费者。可能会有某个消费者Slow;
因为要处理其他复杂的业务逻辑,其消费的效率相对其他消费者比较慢,这个就会造成当其他消费者已经消费完处于空闲状态。
因平均分配原则,队列任会继续把消息发给 Slow 处于忙碌状态,大大降低了系统的性能。
正确的做法的是"能劳者多劳;消费越快的,让其消费的越多"
三、发布订阅模式、路由模式、通配符模式
他们三个都属于订阅模型,订阅模型的共同点: 生产者,一个交换机(fanoutExchange),多个队列,多个消费者。
生产者将消息不是直接发送到队列,而是发送到X交换机,然后由交换机发送给多个队列,多个消费者分别各自监听一个队列,来消费消息。
java
交换机有哪些类型:
1、Fanout:广播,将消息交给所有绑定到交换机的队列
2、Direct:定向,把消息交给符合指定routing key 的队列
3、Topic:通配符是最为常有用的一种,交换机把消息交给符合routing pattern(路由模式)的队列
应用场景:电商网站的同一条促销信息需要短信发送、邮件发送、站内信发送等。此时可以使用发布订阅模式(Publish/Subscribe)
一、发布订阅模式
java
生产者将消息发送给交换机,交换机将消息转发到绑定此交换机的每个队列中,注意是【同一个消息】会转给【所有的队列】。
这里还只是【交换机和队列的关系】,交换机会把一个消息给所有的队列,
但是一个队列,如果绑定多个消费者,那么这个队列,就会采用平均的方式分给消费者。
前面的【工作队列模式】的交换机只能将消息发送给【一个队列】,
而【发布订阅模式】的【交换机】能将【同一个消息】发送给【多个队列】。
注意是多个队列,而且交换机丢给队列的时候,也是采用【轮训】队列的方式,将消息丢给每个队列,发布订阅模式使用fanout交换机。
总结:
订阅模式中,多个消费者同时订阅一个队列,该队列会【轮询】地把消息平均分配给每个消费者,这也就是标准的【工作队列模式】的模型。
通过前面的demo工程可知,我们在使用发布订阅模式时,所有消息都会发送到绑定的队列中。
但很多时候,不是所有消息都【无差别】的发布到所有队列中,因为有的队列处理快有的队列处理慢,这无形当中就会照成不必要的资源浪费。
为了解决这个问题,路由模式就诞生了。
二、路由模式(Routing)
java
路由(Routing)模式是发布订阅模式的升级版。
我们知道发布订阅模式是【无条件】地将所有消息分发给【所有消费者队列】,每个队列中都有相同的消息;
路由模式,由上图很容易理解,每个队列消息会因为绑定的路由不同而不同。
特点:
1、每个队列绑定一个路由关键字RoutingKey,生产者将带有RoutingKey的消息发送给交换机,交换机再根据路由 RoutingKey关键字将消息定向发送到指定的队列中;
2、默认使用 direct 交换机。
java
代码:
// 1、建立交换机
exchangeDeclare("exchange_topic", BuiltinExchangeType.TOPIC);
// 2、创建队列
queueDeclare("queue1"...);
queueDeclare("queue2"...);
queueDeclare("queue3"...);
// 3、交换机+队列+routeKey绑定关系
queueBind("queue1", "routeKey1", 交换机);
queueBind("queue2", "routeKey2", 交换机);
queueBind("queue3", "routeKey3", 交换机);
// 6、发送消息,基于routeKey来发
basicPublish("routeKey1", 消息内容1);
basicPublish("routeKey2", 消息内容2);
路由模式是一种精准的匹配,只有设置了 Routing Key 后消息才能进行分发。
但是,我们在实际的工作中开发需求时还有一些非常模糊的情况,比如消费者存在某种交集的联系只要符合某一个条件,
就需要有消息分发获取消息处理业务逻辑。这时候就需要用到"通配符模式"。
三、通配符模式(Topic)
java
通配符模式(Topic)是在路由模式的基础上升级,给队列绑定带通配符的路由关键字,
只要消息的RoutingKey能实现通配符匹配而不再是固定的字符串,就会将消息转发到该队列。通配符模式比路由模式更灵活。
特点:
1、消息设置RoutingKey时,RoutingKey由多个单词构成,中间以 . 分割。
2、队列设置RoutingKey时,#可以匹配任意多个单词,*可以匹配任意一个单词。
3、使用 topic 交换机。
代码:
java
// 1、建立交换机
exchangeDeclare("exchange_topic", BuiltinExchangeType.TOPIC);
// 2、创建队列
queueDeclare("queue1"...);
queueDeclare("queue2"...);
queueDeclare("queue3"...);
// 3、交换机+队列+routeKey绑定关系
queueBind("queue1", "#.big.#", 交换机);
queueBind("queue2", "#.middle.#", 交换机);
queueBind("queue3", "#.small.#", 交换机);
// 6、发送消息,基于routeKey来发
channel.basicPublish("big.middle", 消息内容);
channel.basicPublish("small", 消息内容);
五种工作模式:全面解读