上文RabbitMQ 入门:1. Message Broker(消息代理)提到过 RabbitMQ 实现了 AMQP 这个协议(RabbitMQ 所支持的 AMQP 的版本是 0.9.1),这个协议的内容很多,但为了构建入门级的分布式应用,我们只需要了解以下几点即可。
在最简单的场景下,RabbitMQ 的架构示意图大致如下:
首先某个消息从发布者那里发往 RabbitMQ
这个消息需要声明一个 Exchange(也可以翻译成交换机),并被发往这个 Exchange
Exchange 有点类似“暂存区”,消息都会发往 Exchange。用个类比来说:Exchange 就像邮箱一样,我们写的信件首先都要放到邮箱里才能进行发送。
然后,Exchange 将使用消息内的一些信息以及它自己的配置来决定一条或多条发送消息的路由。
这些路由都通向一个 Queue(队列),消息会存储在这个 Queue 里,等待消息的接收者来进行使用。
一个消息的接收者可以使用 Queue 中的信息。一旦确认这个消息被传递成功,那么它将从 Queue 中被删除。
RabbitMQ 所提供的松耦合的特性,主要是因为 Exchange 和 Queue 的分离。
继续使用邮箱的类比,Queue 就相当于是接收信件的邮箱。而根据邮件地址,邮件系统会选择不同的邮箱来接收邮件。
而由于 RabbitMQ 处理的是消息,而不是信件,所以它的选项会更多:RabbitMQ 一共有 4 种 Exchange:
Direct Exchange。它是默认的 Exchange 。它会把消息发送到一个接收者。如果注册了多个接收者来监听同样的路由 Key,那么 RabbitMQ 将会向每个 Queue 轮流发送一条消息,相当于提供了一个简单的负载均衡
Fanout Exchange。 它把消息的副本发送到每个绑定到该 Exchange 的 Queue 上面。而这里的 Queue 没有办法对消息进行过滤,如果需要过滤,则需要在消息接收者那里实现。
Topic Exchange。它和 Direct Exchange 类似,但不同的是:每个消息接收者监听特定的路由 Key,它们会收到消息的副本。
例如聊天室就可以使用 Topic Exchange。每个聊天室的 ID 可以作为路由 Key,这样就可以保证消息只会发送给同一个聊天室的其他参与者。
Headers Exchange。这类 Exchange 会忽略路由 Key,取而代之的是,它们会查看消息的 Header,并由此来决定消息应该发往哪个 Queue。Queue 可以有一个或多个 Header 用来进行匹配。这也就开启了复杂的路由场景,例如某个 Queue 有时可以接收到某类消息而有时则不行。
下面仅针对 Fanout Exchange 进行进一步说明:
Fanout Exchange
当消息被发往 RabbitMQ 的时候,需要指明它需要发送到哪个 Exchange。而这个Exchange 就可以被设置成为所谓的 Fanout Exchange。
使用 Fanout Exchange,消息会被克隆,并被发送到所有与这个 Exchange 绑定的 Queue 上,如下图:
这里每一个 Queue 都会得到属于自己的消息的副本,这些消息副本就i可以被消息的接收者所使用。
在很多大规模多人游戏的场景中,经常使用这种方式来同步玩家的数据:每个玩家都订阅到一个Fanout Exchange,你游戏的实例只需要将数据发送到一个地方即可,游戏中其他的玩家就会获得更新,而你的游戏实例就不需要知道如何数据发往每一个玩家了。