什么叫消息队列?
消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。
为何用消息队列?
消息队列是一种应用间的异步协作机制,那什么时候需要使用消息队列呢?像用户下单之后、生成订单、结算,定时给系统注册用户推送活动消息,一些常见的流程类的业务都会用到消息队列服务。
一、RabbitMQ简介
RabbitMQ是一个消息的代理器,用于接收和发送消息,你可以这样想,他就是一个邮局,当您把需要寄送的邮件投递到邮筒之时,你可以确定的是邮递员先生肯定会把邮件发送到需要接收邮件的人的手里,不会送错的。在这个比喻中,RabbitMQ就是一个邮箱,也可以理解为邮局和邮递员,他们负责把消息发送出去和用于接收信息。
RabbitMQ和邮局这两者之间的主要区别是它不会处理纸质邮件,取而代之的是接收、存储和发送二进制数据块,也就是我们通常所说的消息。
二 、RabbitMQ基本概念
下图是RabbitMQ服务的内部结构
- 1)Message
- 消息,它由消息头和消息体两部分组成。消息体是不透明的,但消息头是由一些属性组成的,其中包括:routing-key(路由键)、priority(优先权)、delivery-mode(持久存储)。
- 2)Publisher
- 生产者,也是消息的生产者,它是向交换器发布消息的应用程序
- 3)Exchange
- 交换器,用来接收生产者传递过来的消息,然后将这些消息路由至服务器中的队列
- 4)Binding
- 绑定,用于消息队列与交换器之间的沟通。也是消息路由的规则,相当于一个路由表。
- 5)Queue
- 消息队列,用来保存消息直到发送给消费者。一个消息可以进入一个或多个队列,除消费者取走消息,否则它一直在消息队列里。
- 6)Connection
- 网络连接,如:一个TCP连接
- 7)Channel
- 信道,多路复用连接中一个独立的双向数据传输通道。无论是发布消息、订阅队列、接收消息都是通过信道来完成。复用信道是为了降低系统资源的消耗。
- 8)Consumer
- 消费者,也就是接收生产者发来的消息的客户端应用。
- 9)Virtual Host
- 虚拟主机,交换器、消息队列相关的对象。一个VHOST其实可以看成一个rabbitmp服务器,它拥有自己的队列、交换器、绑定与权限机制等。Rabbitmq默认vhost是/。
三、RabbitMQ 特点
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。
RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
具体特点包括:
参考文章 http://www.rabbitmq.com/
四、Rabbitmq的工作过程
- 1)客户端连接到消息队列服务器,开启一个channel
- 2)客户端声明一个exchange、queue,并配置相关属性
- 3)客户端使用routing key,在exchange与queue之间建立好绑定关系
- 4)客户端传递消息到交换器
- 5)交换器接收到消息后,根据预定的KEY与绑定关系,对消息进行路由至消息队列
五、Rabbitmq服务安装布署
1)首先需要安装Erlang环境
https://bintray.com/rabbitmq/rpm/erlang
2)下载安装Rabbitmq
https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.6/rabbitmq-server-3.7.6-1.el7.noarch.rpm
六、Rabbitmq CLI介绍
自带多个命令行工具
1)rabbitmqctl #管理与操作命令
- 停止节点
- 访问节点状态,有效配置,运行状况检查
- 虚拟主机管理
- 用户和权限管理
- 政策管理
- 列出队列,连接,渠道,交流,消费者
- 集群成员管理
七、RabbitMQ集群
RabbitMQ 是用 erlang 开发的,集群非常方便,因为 erlang 天生就是一门分布式语言,但其本身并不支持负载均衡。
RabbitMQ 的集群节点包括:
不过,如前文所述,如果在投递消息时,打开了消息的持久化,那即使是内存节点,数据还是安全的放在磁盘。一个 RabbitMQ 集群中可以共享 user、vhost、queue、exchange 等,所有的数据和状态都是必须在所有节点上复制的,一个例外是那些当前只属于创建它的节点的消息队列,尽管它们可见且可被所有节点读取。 RabbitMQ 节点可以动态地加入到集群中,一个节点它可以加入到集群中,也可以从集群环集群进行一个基本的负载均衡。
Rabbit 模式大概分为以下三种:
单一模式:最简单的情况,非集群模式。
普通模式:默认的集群模式。
对于 Queue 来说,消息实体只存在于其中一个节点,A、B 两个节点仅有相同的元数据,即队列结构。当消息进入 A 节点的 Queue 中后,consumer 从 B 节点拉取时,RabbitMQ 会临时在 A、B 间进行消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer. 所以 consumer 应尽量连接每一个节点,从中取消息。即对于同一个逻辑队列,要在多个节点建立物理 Queue。否则无论 consumer 连 A 或 B,出口总在 A,会产生瓶颈。该模式存在一个问题就是当 A 节点故障后,B 节点无法取到 A 节点中还未消费的消息实体。如果做了消息持久化,那么得等 A 节点恢复,然后才可被消费。
镜像模式:
把需要的队列做成镜像队列,存在于多个节点,属于 RabbitMQ 的 HA 方案。
该模式解决了上述问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在 consumer 取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所,在对可靠性要求较高的场合中适用。