紧接上文:快速入门分布式消息队列之 RabbitMQ(上),继续来看 RabbitMQ 都有哪些值得我们关注的特性。

Message Acknowledgment 消息应答

假设一个场景,消费者接收到了消息,但却在处理消息的过程中发生了意外退出的情况,那么此次消息的传递就应该被视为「无效传递」。显然「无效传递」的情况是不允许在对结果敏感的场景中出现的。

为了解决这个问题,RabbitMQ 规定了队列在把消息传递给消费者之后并不会立即将消息从队列中丢弃,而是要求队列在接收到消费者的 ACK 响应之后,才将其丢弃。如果队列传递消息之后的一段时间内仍未能接收到消费者的 ACK,那么消息就会传递给别的消费者处理直到队列接收到 ACK 响应为止,以此来确保每一个消息都能被有效的传递,这就是 RabbitMQ 的消息应答机制

消息应答机制默认是开启的,当然了,如果在对结果响应无所谓的场景中,我们完全可以关闭掉它(autoAsk=true),因为开启消息应答机制反而会降低消息传递的效率。

Prefetch Count 预取数

RabbitMQ 支持消费者每次从队列中获取任意数量的消息,这就是所谓的预取。如果消费者所执行的任务是相对细小的,那么就应该每次预取更多的消息数量。这是因为不同消费者执行的任务长度不尽相同,如果使用均分的方式来分配消息的话,那么任务粒度小、执行时间短的消费者就会闲置下来。

这种情况在开启消息应答机制时尤为明显,所以建议为任务粒度较小的消费者设定更大的预取数值。

RPC 远程过程调用

RabbitMQ 除了支持异步通讯之外,同时也会支持同步通讯来满足用户多方面的需求。其提供的 RPC(Remote Procedure Call,远程调用)就是一种同步通讯方式,其实现的原理如下:

  • 生产者在生产请求消息时,会在请求消息的属性中设置两个 replyTo 值:一个为 Queue Name,用于告知消费者将应答消息返回到该队列;另一个为 correlationId,是请求消息的唯一标示,随着请求消息一同发送给消费者,也会随着响应消息返回给生产者。这样生产者就能够通过 correlationId 来判定响应消息对应的请求消息,最终实现请求和响应的一一配对。

  • 并且生产者只有在接收到响应消息之后才会继续发出下一次请求消息,以此实现同步的效果。

刚刚接触 RabbitMQ 的话,可能会直观的认为它只能支持异步的通讯方式,其实不然,只是应用异步的场景更多而已。

vhost 虚拟主机

RabbitMQ 支持通过 vhost 虚拟主机功能来实现多租户的效果,每一个 vhost 就相当于一个 Mini RabbitMQ,均拥有着属于自己的队列、交换机和绑定。而且不同 vhost 之间的命名空间彼此独立、互相隔离,有效的解决了命名冲突的问题。所以一个 RabbitMQ 服务器实际上能够同时服务于多个不同的应用程序。

(下文代码块中的 ‘$’ 均表示指令行输入)
RabbitMQ 服务器默认的虚拟主机为 “/”,缺省账户为 guest。

$ rabbitmqctl list_vhosts
Listing vhosts ...
/
…done.

$ rabbitmqctl list_users
Listing users ...
guest    [administrator]
...done.

为应用程序 web_app 分配一个独立的虚拟主机。
Step 1:新建一个用户,并为其设定为超级管理员角色。

$ rabbitmqctl add_user mickey passw0rd
Creating user "mickey" ...
...done.

$ rabbitmqctl set_user_tags mickey administrator
Setting tags for user "mickey" to [administrator] ...
...done.

# rabbitmqctl list_users
Listing users ...
guest    [administrator]
mickey    [administrator]
...done.

NOTE:RabbitMQ 具有下列 5 种角色类型:

  • none 最小权限角色,不能登录管理页面。
  • management 管理员角色,能够访问虚拟主机的队列、绑定、交换机、通道和连接等。
  • policymaker 决策者角色,包含但不限于 management 的权限,还具有查看、创建和删除策略和参数的权限。
  • monitoring 监控角色,包含但不限于 management 的权限,还具有查看其它类型账户的通道、连接属性,也能够获取虚拟主机清单。
  • administrator 超级管理员角色,最高权限。

Step 2:新建一个虚拟主机

$ rabbitmqctl add_vhost web_app
Creating vhost "web_app" ...
...done.

$ rabbitmqctl list_vhosts
Listing vhosts ...
/
web_app
…done.

Step 3:绑定用户在虚拟主机中的权限

$ rabbitmqctl list_user_permissions mickey
Listing permissions for user "mickey" ...
...done.

$ rabbitmqctl set_permissions -p web_app mickey '.*' '.*' '.*'
Setting permissions for user "mickey" in vhost "web_app" ...
...done.

$ rabbitmqctl list_user_permissions mickey
Listing permissions for user "mickey" ...
web_app    .*    .*    .*
…done.

NOTE:选项 set_permissions 后面跟着三个 ‘.*’ 参数分别表示为用户在虚拟机上的 配置(创建/删除队列和交换机)、读(获取消息)、写(发布消息) 权限。

插件系统

RabbitMQ 支持强大的插件系统,当我们需要一个 RabbitMQ 没有提供的功能时,第一反应应该是到网上查找有没有相应的插件模块。

通过访问 (http://www.rabbitmq.com/plugins.html) 来查看 RabbitMQ 官方提供的插件列表,其中 「Supported Plugins」列表由官方团队维护,可以放心的在生产环节中使用,至于其他实验性质的插件列表则建议慎重考虑。

最常用的插件模块之一就是 rabbitmq_management,它可以让我们通过 Web 或 RESTful API 来管理 RabbitMQ。

安装 rabbitmq_management 插件:

$ rabbitmq-plugins enable rabbitmq_management
The following plugins have been enabled:
  mochiweb
  webmachine
  rabbitmq_web_dispatch
  amqp_client
  rabbitmq_management_agent
  rabbitmq_management
Plugin configuration has changed. Restart RabbitMQ for changes to take effect.

$ service rabbitmq-server restart
 * Restarting message broker rabbitmq-server                        [ OK ]

通过访问 http://localhost:15672 来登录 RabbitMQ Web 管理平台。

RabbitMQ Web 管理平台主要有「全局统计预览/连接管理/通道管理/交换机管理/队列管理/全局设置管理」等几个板块组成,支持下面常用的管理操作:

  • RabbitMQ 服务器的动态数据统计预览。
  • 查看服务器连接列表,关闭指定连接。
  • 查看连接的通道列表
  • 查看交换机列表,新建/删除交换机,新建/修改交互机与队列的绑定,发布消息。
  • 查看队列列表,新建/删除队列,新建/修改队列与交互机的绑定,发布消息,获取消息。
  • 查看用户列表,添加用户。
  • 查看虚拟主机列表,添加虚拟主机。
  • 查看策略列表,添加/更改策略。

最后

本篇主要介绍了 RabbitMQ 的消息应答、预取数、RPC、虚拟主机和插件系统等特性,我们在应用 RabbitMQ 之前,应该对这些特性有充分的了解,才能够针对不同的项目场景作出合适的配置和选择。

下一篇:快速入门分布式消息队列之 RabbitMQ(下)

本文转自:https://mp.weixin.qq.com/s?__biz=MzI3MDM0NjU3MA==&mid=2247483964&idx=1&sn=836822e7131888b7af91c1053d319f23&chksm=ead33219dda4bb0f9196a9fc40cce5252896edbe02bfd70a648afaa60a03872a5db1e78fc7f1&mpshare=1&scene=23&srcid=1206YjgtUi7ALQ9ByJrR5kYP#rd