感兴趣的同学可以灌水哦,网址:http://www.wangkun.xyz/
欢迎来找bug和提(gao)需(shi)求(qing)
支持QQ和微博快捷登录,免注册,想要相关源码请发布问答留言
消息队列中间件简介
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量 削锋等问题实现高性能,高可用,可伸缩和终一致性[架构] 使用较多的消息队列有 ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ
什么是RabbitMQ
RabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。
RabbitMQ 初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展 性、高可用性等方面表现不俗。具体特点包括:
1.可靠性(Reliability)
RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
2.灵活的路由(Flexible Routing)
北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090
在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
3.消息集群(Clustering)
多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。 4.高可用(Highly Available Queues)
队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
5.多种协议(Multi-protocol)
RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。
6.多语言客户端(Many Clients) RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。
7.管理界面(Management UI)
RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方 面。
8.跟踪机制(Tracing)
如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。 9.插件机制(Plugin System)
RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。
## 主要概念 ##
RabbitMQ Server: 也叫broker server,它是一种传输服务。 他的角色就是维护一条 从Producer到Consumer的路线,保证数据能够按照指定的方式进行传输。
Producer:
消息生产者,如图A、B、C,数据的发送方。消息生产者连接RabbitMQ服 务器然后将消息投递到Exchange。
#Consumer:消息消费者,如图1、2、3,数据的接收方。消息消费者订阅队列, RabbitMQ将Queue中的消息发送到消息消费者。
Exchange:生产者将消息发送到Exchange(交换器),由Exchange将消息路由到一个 或多个Queue中(或者丢弃)。Exchange并不存储消息。RabbitMQ中的Exchange有 direct、fanout、topic、headers四种类型,每种类型对应不同的路由规则。
#Queue:
(队列)是RabbitMQ的内部对象,用于存储消息。消息消费者就是通过订阅 队列来获取消息的,RabbitMQ中的消息都只能存储在Queue中,生产者生产消息并终 投递到Queue中,消费者可以从Queue中获取消息并消费。多个消费者可以订阅同一个 Queue,这时Queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者 都收到所有的消息并处理。
#RoutingKey:
生产者在将消息发送给Exchange的时候,一般会指定一个routing key, 来指定这个消息的路由规则,而这个routing key需要与Exchange Type及binding key联 合使用才能终生效。在Exchange Type与binding key固定的情况下(在正常使用时一 般这些内容都是固定配置好的),我们的生产者就可以在发送消息给Exchange时,通过 指定routing key来决定消息流向哪里。RabbitMQ为routing key设定的长度限制为255 bytes。
#Connection: (连接):
Producer和Consumer都是通过TCP连接到RabbitMQ Server 的。以后我们可以看到,程序的起始处就是建立这个TCP连接。
Channels: (信道):
它建立在上述的TCP连接中。数据流动都是在Channel中进行 的。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。
VirtualHost:
权限控制的基本单位,一个VirtualHost里面有若干Exchange和 MessageQueue,以及指定被哪些user使用
1、什么是RabbitMQ?为什么使用RabbitMQ?
答:RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的,消息中间件;
可以用它来:解耦、异步、削峰。
2、RabbitMQ有什么优缺点?
答:优点:解耦、异步、削峰;
缺点:降低了系统的稳定性:本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;
增加了系统的复杂性:加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。
3、如何保证RabbitMQ的高可用?
答:没有哪个项目会只用一搭建一台RabbitMQ服务器提供服务,风险太大;
4、如何保证RabbitMQ不被重复消费?
答:先说为什么会重复消费:正常情况下,消费者在消费消息的时候,消费完毕后,会发送一个确认消息给消息队列,消息队列就知道该消息被消费了,就会将该消息从消息队列中删除;
但是因为网络传输等等故障,确认信息没有传送到消息队列,导致消息队列不知道自己已经消费过该消息了,再次将消息分发给其他的消费者。
针对以上问题,一个解决思路是:保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响;保证消息等幂性;
比如:在写入消息队列的数据做唯一标示,消费消息时,根据唯一标识判断是否消费过;
5、如何保证RabbitMQ消息的可靠传输?
答:消息不可靠的情况可能是消息丢失,劫持等原因;
丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息;
生产者丢失消息:从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息;
transaction机制就是说:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务(channel.txCommit())。然而,这种方式有个缺点:吞吐量下降;
confirm模式用的居多:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;
rabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;
如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。
消息队列丢数据:消息持久化。
处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。
这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。
这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。
那么如何持久化呢?
这里顺便说一下吧,其实也很容易,就下面两步
将queue的持久化标识durable设置为true,则代表是一个持久的队列
发送消息的时候将deliveryMode=2
这样设置以后,即使rabbitMQ挂了,重启后也能恢复数据
消费者丢失消息:消费者丢数据一般是因为采用了自动确认消息模式,改为手动确认消息即可!
消费者在收到消息之后,处理消息之前,会自动回复RabbitMQ已收到消息;
如果这时处理消息失败,就会丢失该消息;
解决方案:处理消息成功后,手动回复确认消息。
6、如何保证RabbitMQ消息的顺序性?
答:单线程消费保证消息的顺序性;对消息进行编号,消费者处理消息是根据编号处理消息;
问题一:RabbitMQ 中的 broker 是指什么?cluster 又是指什么?
答:broker 是指一个或多个 erlang node 的逻辑分组,且 node 上运行着 RabbitMQ 应用
程序。cluster 是在 broker 的基础之上,增加了 node 之间共享元数据的约束。
问题二:什么是元数据?元数据分为哪些类型?包括哪些内容?与 cluster 相关的元数据
有哪些?元数据是如何保存的?元数据在 cluster 中是如何分布的?
答:在非 cluster 模式下,元数据主要分为 Queue 元数据(queue 名字和属性等)、
Exchange 元数据(exchange 名字、类型和属性等)、Binding 元数据(存放路由关系的查
找表)、Vhost 元数据(vhost 范围内针对前三者的名字空间约束和安全属性设置)。在
cluster 模式下,还包括 cluster 中 node 位置信息和 node 关系信息。元数据按照 erlang
node 的类型确定是仅保存于 RAM 中,还是同时保存在 RAM 和 disk 上。元数据在
cluster 中是全 node 分布的。
问题三:RAM node 和 disk node 的区别?
答:RAM node 仅将 fabric(即 queue、exchange 和 binding 等 RabbitMQ 基础构件)相
关元数据保存到内存中,但 disk node 会在内存和磁盘中均进行存储。RAM node 上唯一
会存储到磁盘上的元数据是 cluster 中使用的 disk node 的地址。要求在 RabbitMQ cluster
中至少存在一个 disk node 。
问题四:RabbitMQ 上的一个 queue 中存放的 message 是否有数量限制?
答:可以认为是无限制,因为限制取决于机器的内存,但是消息过多会导致处理效率的下
降。
问题五:RabbitMQ 概念里的 channel、exchange 和 queue 这些东东是逻辑概念,还是对应着进程实体?这些东东分别起什么作用?
答:queue 具有自己的 erlang 进程;exchange 内部实现为保存 binding 关系的查找表;
channel 是实际进行路由工作的实体,即负责按照 routing_key 将 message 投递给
queue 。由 AMQP 协议描述可知,channel 是真实 TCP 连接之上的虚拟连接,所有
AMQP 命令都是通过 channel 发送的,且每一个 channel 有唯一的 ID。一个 channel 只
能被单独一个操作系统线程使用,故投递到特定 channel 上的 message 是有顺序的。但
一个操作系统线程上允许使用多个 channel 。channel 号为 0 的 channel 用于处理所有
对于当前 connection 全局有效的帧,而 1-65535 号 channel 用于处理和特定 channel 相
关的帧。AMQP 协议给出的 channel 复用模型如下
其中每一个 channel 运行在一个独立的线程上,多线程共享同一个 socket。
问题六:vhost 是什么?起什么作用?
答:vhost 可以理解为虚拟 broker ,即 mini-RabbitMQ server。其内部均含有独立的
queue、exchange 和 binding 等,但最最重要的是,其拥有独立的权限系统,可以做到
vhost 范围的用户控制。当然,从 RabbitMQ 的全局角度,vhost 可以作为不同权限隔离
的手段(一个典型的例子就是不同的应用可以跑在不同的 vhost 中)。