Message Broker(消息代理)
维基百科对 Message Broker 的定义是:Message broker 是一种中介程序模块,它把消息从发送方的正式消息传递协议转化为接收方的正式消息传递协议。
这个定义略繁琐,下面看看 RabbitMQ 官网对 Message broker 的定义:
Message broker 接收来自发布者的消息并将其路由到消费者。
上面两个定义说的都是同一件事情,但是 RabbitMQ 官网的定义里缺少了“转换”这部分。
RabbitMQ 实现了一个加 AMQP(Advanced Message Queuing Protocol)的协议,AMQP 就如果互联网的 HTTP 协议,它更注重于如何传输数据,并不关心发送的数据是什么。这也就意味着需要消息的发送者和接收者来协调消息的格式。
为什么需要 Message broker?
看下图。有这样一个应用,客户端需要与服务器进行通信,传递数据。最简单的情况就是客户端通过 HTTP 类协议直接与服务器连接,并发送数据。
目前一切都很简单明了。
但是,如果服务器因为维护或其它原因发生了停机,或者你想对其横向扩展,添加更多的服务器来进行响应。那么问题就来了,客户端目前是与这台服务器紧密的耦合在一起了,而随着系统的增长和进化,这种紧耦合就开始让人头疼。
如果,我们在客户端与服务器之间放置一个 Message broker,那么情况就不一样了:
客户端首先将数据发送给 Message broker。Message broker 会对数据进行检验,并将其发送给服务器。
但是在这种简单的情景下,感觉没带来什么好处。
但是,Message broker 可以通过简单的设置来允许多种场景,从而让后端服务器的横向扩展或停机维护等工作变得轻松,并且客户端并不会感知到任何的变化。
这种解耦的架构在分布式应用中非常的常见,这意味着所有一切所唯一依赖可用的东西就是 Message broker。因为 Message broker 唯一的工作就是传输数据,所以没有必要经常对其进行改动,所以它是一个相对安全可靠的组件。
对于像 RabbitMQ 这样可以设置集群来支持高可用的 Message broker,更是这样。
Exchange 和 Queue(消息交换和队列)
上文提到过 RabbitMQ 实现了 AMQP 这个协议(RabbitMQ 所支持的 AMQP 的版本是 0.9.1),这个协议的内容很多,但为了构建入门级的分布式应用,我们只需要了解以下几点即可。
在最简单的场景下,RabbitMQ 的架构示意图大致如下:
· 首先某个消息从发布者那里发往 RabbitMQ
· 这个消息需要声明一个 Exchange(也可以翻译成交换机),并被发往这个 Exchange
o Exchange 有点类似“暂存区”,消息都会发往 Exchange。用个类比来说:Exchange 就像邮箱一样,我们写的信件首先都要放到邮箱里才能进行发送。
· 然后,Exchange 将使用消息内的一些信息以及它自己的配置来决定一条或多条发送消息的路由。
· 这些路由都通向一个 Queue(队列),消息会存储在这个 Queue 里,等待消息的接收者来进行使用。
· 一个消息的接收者可以使用 Queue 中的信息。一旦确认这个消息被传递成功,那么它将从 Queue 中被删除。
o RabbitMQ 所提供的松耦合的特性,主要是因为 Exchange 和 Queue 的分离。
o 继续使用邮箱的类比,Queue 就相当于是接收信件的邮箱。而根据邮件地址,邮件系统会选择不同的邮箱来接收邮件。
而由于 RabbitMQ 处理的是消息,而不是信件,所以它的选项会更多:RabbitMQ 一共有 4 种 Exchange:
· Direct Exchange。它是默认的 Exchange 。它会把消息发送到一个接收者。如果注册了多个接收者来监听同样的路由 Key,那么 RabbitMQ 将会向每个 Queue 轮流发送一条消息,相当于提供了一个简单的负载均衡
· Fanout Exchange。 它把消息的副本发送到每个绑定到该 Exchange 的 Queue 上面。而这里的 Queue 没有办法对消息进行过滤,如果需要过滤,则需要在消息接收者那里实现。
· Topic Exchange。它和 Direct Exchange 类似,但不同的是:每个消息接收者监听特定的路由 Key,它们会收到消息的副本。
o 例如聊天室就可以使用 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 都会得到属于自己的消息的副本,这些消息副本就可以被消息的接收者所使用。
在很多大规模多人游戏的场景中,经常使用这种方式来同步玩家的数据:每个玩家都订阅到一个 Fanout Exchange,你游戏的实例只需要将数据发送到一个地方即可,游戏中其他的玩家就会获得更新,而你的游戏实例就不需要知道如何数据发往每一个玩家了。
安装 RabbitMQ 和常用工具
RabbitMQ 是使用 Erlang 语言编写的,这也是 RabbitMQ 能够提供如此高的可靠性的原因之一。
安装 RabbitMQ
所以,如果想使用 RabbitMQ,就必须安装 Erlang。
以 Windows 操作系统为例,我们可以去 Erlang 官方网站下载 Erlang 的安装包进行安装,而我更喜欢 chocolatey ( https://chocolatey.org/ ) 这个 Windows 操作系统的包管理工具。
1. 安装 Chocolatey:
a. 使用管理员打开 Powershell
b. 运行 Get-ExecutionPolicy,如果返回是 Restricted,那么运行 Set-ExecutionPolicy AllSigned 或者 Set-ExecutionPolicy Bypass -Scope Process
c. 然后执行命令:Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
回车,等一会就安装完了。
d. 最后输入 choco -? 命令试一下,如果出现类似以下结果,就说明安装成功了:
2. 使用 Chocolatey 安装 RabbitMQ:可以在 https://chocolatey.org/packages 搜索 RabbitMQ。找到 RabbitMQ 之后,按页面提示,使用 choco install rabbitmq 命令进行安装即可。(安装的过程中应该会自动安装依赖的 Erlang,如果不行,那么就搜索 Erlang,先安装 Erlang 即可)。
在其他操作系统安装 RabbitMQ 的过程请查看官方文档:https://www.rabbitmq.com/download.html
使用命令行与 RabbitMQ 交互
在 Windows 10 上,按 Windows S 进行搜索,输入 RabbitMQ,或得到以下结果:
最上面的 RabbitMQ Command Prompt 就是安装包提供的一个快捷命令行链接,它指向 RabbitMQ 的 sbin 目录。而 RabbitMQ 所提供的命令行工具都在这个目录下。
正常情况下,在 Windows 10 系统中安装完 RabbitMQ 之后,它会以 Windows 服务的形式运行:
但如果 RabbitMQ 没有做为 Windows 服务存在,那么可以手动按如下步骤让其启动运行:
1. 打开 RabbitMQ 命令行
2. 输入 rabbitmq-server 命令
由于我的 RabbitMQ 是以 Windows 服务的形式已经在运行,所以这里提示 25672 端口被占用等信息。
部分常用命令简介
这里主要简单介绍几个 rabbitmqctl 工具的命令。
1. 获取 RabbitMQ Server 状态
命令为 rabbitmqctl status,该命令执行后会提供大量关于 RabbitMQ 运行的环境信息,:
2. 获取所有 Queue 队列
运行命令 rabbitmqctl list_queues,该命令会返回 RabbitMQ 所建立的 Queue(队列)及其信息。
3. 当前集群内的 server 信息
运行命令 rabbitmqctl cluster_status,运行该命令可以知道集群内哪些 server 在一起协调工作。当对 RabbitMQ 进行横向扩展或实现高可用消息通信基础架构时,就可以使用该命令查找相关信息。
更多关于 RabbitMQ 工具和 rabbitmqctl 工具的命令可以查看官方文档:
https://www.rabbitmq.com/cli.html
https://www.rabbitmq.com/rabbitmqctl.8.html
RabbitMQ 的插件
RabbitMQ 也提供了一套插件模型,使用插件可以为 RabbitMQ 提供一些特殊定制化的功能。
RabbitMQ 插件的命令时 rabbitmq-plugins,如果不加任何参数,将会得到类似以下的结果,也就是该命令的一些帮助:
1. 列出所有插件
使用 rabbitmq-plugins list 命令可以列出所有的插件:
其中 *E 表示该插件被启用了,*e 表示该插件是为了支撑其它插件而被隐式启用了。
2. 停用插件
使用命令:rabbitmq-plugins disable 插件名称。停用之后,其它支撑它的插件,如果没有其它需要的话,也会被停用。
命令执行后,会立即反应到当前正在运行的 RabbitMQ 运行时中。
3. 启用插件
使用命令:rabbitmq-plugins enable 插件名称
关于插件,更多的功能信息请查看官方文档:https://www.rabbitmq.com/rabbitmq-plugins.8.html
RabbitMQ 管理控制台
RabbitMQ 的管理控制台是 RabbitMQ 的一个插件,可以通过 rabbitmq-plugins list 命令来查看管理控制台是否已经启用(上图表示已在运行),默认应该是启动的。
启动管理控制台插件后,用浏览器打开网址 http://localhost:15672/ :
首先需要登陆,用户名密码为 guest。登陆成功后进入 Overview 画面,这里会展示一些总体情况:
而 Exchange 页面会展示目前 Server 可用的 Exchange 有哪些:
这里除了 SensorDiscovery,其它都是默认提供的 Exchange。
管理控制台的其它功能,随着后续程序的编写再顺便介绍。