说到rabbitMQ,就不得不提下AMQP(advanced Message Queuing Protocol)高级消息队列协议。redis
AMQP是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件而设计的。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不一样产品,不一样的开发语言等条件的限制。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。算法
上图即AMQP消息队列的模型。数据库
Publisher即消息的生产者,消息生产者负责生产消息并发布到消息队列中。编程
Consumer即消息的消费者,消费者负责从消息队列中取出消息,并对消息作相应的处理。缓存
中间大矩形中的全部能够理解成一个消息队列服务器。安全
AMQP是一个协议标准,一个规范,rabbitMQ是具体的实现。服务器
##为何要使用消息队列。 刚接触消息队列的人可能会有一些误解。网络
前面也说了,amqp最大的特色是解耦,不一样系统,不一样编程语言之间能够通行协同工做。其次就可拓展的灵活性,由于消息队列解耦了你的处理过程,把消息发布与消息处理分离。那消息分发的灵活性,消息处理频率的灵活性便可很好的调节。并发
####总结使用消息队列的好处以下:负载均衡
一、解耦。在项目启动之初来预测未来项目会碰到什么需求,是极其困难的。消息队列在处理过程当中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。这容许你独立的扩展或修改两边的处理过程,只要确保它们遵照一样的接口约束。
二、冗余。有时在处理数据的时候处理过程会失败。除非数据被持久化,不然将永远丢失。消息队列把数据进行持久化直到它们已经被彻底处理,经过这一方式规避了数据丢失风险。在被许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除以前,须要你的处理过程明确的指出该消息已经被处理完毕,确保你的数据被安全的保存直到你使用完毕。
三、扩展性。由于消息队列解耦了你的处理过程,因此增大消息入队和处理的频率是很容易的;只要另外增长处理过程便可。不须要改变代码、不须要调节参数。扩展就像调大电力按钮同样简单。
四、灵活性 & 峰值处理能力。当你的应用上了Hacker News的首页,你将发现访问流量攀升到一个不一样寻常的水平。在访问量剧增的状况下,你的应用仍然须要继续发挥做用,可是这样的突发流量并不常见;若是为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列可以使关键组件顶住增加的访问压力,而不是由于超出负荷的请求而彻底崩溃。请查看咱们关于峰值处理能力的博客文章了解更多此方面的信息。
五、可恢复性。当体系的一部分组件失效,不会影响到整个系统。消息队列下降了进程间的耦合度,因此即便一个处理消息的进程挂掉,加入队列中的消息仍然能够在系统恢复后被处理。而这种容许重试或者延后处理请求的能力一般是造就一个略感不便的用户和一个沮丧透顶的用户之间的区别。
六、送达保证。消息队列提供的冗余机制保证了消息能被实际的处理,只要一个进程读取了该队列便可。在此基础上,IronMQ提供了一个"只送达一次"保证。不管有多少进程在从队列中领取数据,每个消息只能被处理一次。这之因此成为可能,是由于获取一个消息只是"预约"了这个消息,暂时把它移出了队列。除非客户端明确的表示已经处理完了这个消息,不然这个消息会被放回队列中去,在一段可配置的时间以后可再次被处理。
七、异步通讯。不少时候,你不想也不须要当即处理消息。消息队列提供了异步处理机制,容许你把一个消息放入队列,但并不当即处理它。你想向队列中放入多少消息就放多少,而后在你乐意的时候再去处理它们
八、排序保证。在许多状况下,数据处理的顺序都很重要。消息队列原本就是排序的,而且能保证数据会按照特定的顺序来处理。IronMO保证消息浆糊经过FIFO(先进先出)的顺序来处理,所以消息在队列中的位置就是从队列中检索他们的位置
九、缓冲。在任何重要的系统中,都会有须要不一样的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。消息队列经过一个缓冲层来帮助任务最高效率的执行--写入队列的处理会尽量的快速,而不受从队列读的预备处理的约束。该缓冲有助于控制和优化数据流通过系统的速度。
十、 理解数据流。在一个分布式系统里,要获得一个关于用户操做会用多长时间及其缘由的整体印象,是个巨大的挑战。消息系列经过消息被处理的频率,来方便的辅助肯定那些表现不佳的处理过程或领域,这些地方的数据流都不够优化。
消息队列运做能够理解成收发快递的运做。 消息发布者至关于发件人;消息的消费者至关于收件人;整个快递公司至关于消息队列的服务器;快递员至关消息队列服务器中的消息队列。
####AMQP中的几个对象以下:
1.publisher。 消息的发布者。发件人 2.Consumer。 消息的消费者。 收件人 3.Exchange。 交换机。这儿能够理解为快递点,负责把消息(快递)分发到对应的queue(快递员)中。 5.Queue。 用来存储消息的队列(快递员)。
####AMQP中的几个概念
1.Binding。 绑定,是把Exchange和queue之联系起来。binding key就是联系的规则。这儿能够把Exchange理解为快递点,queue能够理解为快递员。binding就是快递点和快递员之间的协商,快递员负责的哪一片区域。binding key能够理解为快递员负责的区域。 2.binding key。 Exchange和queue之间的链接规则,快递员负责的区域。 3.routing key。消息生产者生产的消息中携带的Exchange到queue之间的规则。这儿能够理解为快递中的具体地址,是属于每个消息(快递包裹)的属性。binding key是Exchange和queue之间的关系。基本上binding key和routing key的做用是相同,没多大却别。 4.Message acknowledgment。 消息确认回执。即消费者收到消息后,给消息队列服务器的确认回执,相似于快递回执单。 5.Message durability。 消息的持久化,在系统宕机后,能够恢复没出来完的消息。 6.Prefetch count。预取消息。在多个消费者共享一个队列的案例中,明确指定在收到下一个确认回执前每一个消费者一次能够接受多少条消息是很是有用的。
交换机是用来发送消息的AMQP实体。交换机拿到一个消息以后将它路由给一个或零个队列。它使用哪一种路由算法是由交换机类型和被称做绑定(bindings)的规则所决定的。AMQP 0-9-1的代理提供了四种交换机
Name(交换机类型) | Default pre-declared names(预声明的默认名称) | 说明 |
---|---|---|
Direct exchange(直连交换机) | (Empty string) and amq.direct | routing key必须和binding key彻底匹配 |
Fanout exchange(扇型交换机) | amq.fanout | binding key无效,Exchange会把消息发送到全部bind到该Exchange的queue |
Topic exchange(主题交换机) | amq.topic | binding key与routing key只须要一个匹配上,即会转发消息 |
Headers exchange(头交换机) | amq.match (and amq.headers in RabbitMQ) | 使用消息的属性进行匹配,binding key不起做用 |
除交换机类型外,在声明交换机时还能够附带许多其余的属性,其中最重要的几个分别是: |
交换机能够有两个状态:持久(durable)、暂存(transient)。持久化的交换机会在消息代理(broker)重启后依旧存在,而暂存的交换机则不会(它们须要在代理再次上线后从新被声明)。然而并非全部的应用场景都须要持久化的交换机。
默认交换机(default exchange)其实是一个由消息代理预先声明好的没有名字(名字为空字符串)的直连交换机(direct exchange)。它有一个特殊的属性使得它对于简单应用特别有用处:那就是每一个新建队列(queue)都会自动绑定到默认交换机上,绑定的键(binding key)名称与队列名称相同。默认交换机能够理解成一个特殊的直连交换机。
直连型交换机(direct exchange)是根据消息携带的路由键(routing key)将消息投递给对应队列的。直连交换机用来处理消息的单播路由(unicast routing)(尽管它也能够处理多播路由)。下边介绍它是如何工做的:
直连型交换机图例:
扇型交换机(funout exchange)将消息路由给绑定到它身上的全部队列,而不理会绑定的路由键。若是N个队列绑定到某个扇型交换机上,当有消息发送给此扇型交换机时,交换机会将消息的拷贝分别发送给这全部的N个队列。扇型用来交换机处理消息的广播路由(broadcast routing)。
由于扇型交换机投递消息的拷贝到全部绑定到它的队列,因此他的应用案例都极其类似:
扇型交换机图例:
有时消息的路由操做会涉及到多个属性,此时使用消息头就比用路由键更容易表达,头交换机(headers exchange)就是为此而生的。头交换机使用多个消息属性来代替路由键创建路由规则。经过判断消息头的值可否与指定的绑定相匹配来确立路由规则。
咱们能够绑定一个队列到头交换机上,并给他们之间的绑定使用多个用于匹配的头(header)。这个案例中,消息代理得从应用开发者那儿取到更多一段信息,换句话说,它须要考虑某条消息(message)是须要部分匹配仍是所有匹配。上边说的“更多一段消息”就是"x-match"参数。当"x-match"设置为“any”时,消息头的任意一个值被匹配就能够知足条件,而当"x-match"设置为“all”的时候,就须要消息头的全部值都匹配成功。
头交换机能够视为直连交换机的另外一种表现形式。头交换机可以像直连交换机同样工做,不一样之处在于头交换机的路由规则是创建在头属性值之上,而不是路由键。路由键必须是一个字符串,而头属性值则没有这个约束,它们甚至能够是整数或者哈希值(字典)等。
消息队列是用来缓存消息。 由Exchange把消息推送到queue中。
持久化队列(Durable queues)会被存储在磁盘上,当消息代理(broker)重启的时候,它依旧存在。没有被持久化的队列称做暂存队列(Transient queues)。并非全部的场景和案例都须要将队列持久化。
持久化的队列并不会使得路由到它的消息也具备持久性。假若消息代理挂掉了,从新启动,那么在重启的过程当中持久化队列会被从新声明,不管怎样,只有通过持久化的消息才能被从新恢复。
绑定(Binding)是交换机(exchange)将消息(message)路由给队列(queue)所需遵循的规则。若是要指示交换机“E”将消息路由给队列“Q”,那么“Q”就须要与“E”进行绑定。绑定操做须要定义一个可选的路由键(routing key)属性给某些类型的交换机。路由键的意义在于从发送给交换机的众多消息中选择出某些消息,将其路由给绑定的队列。 打个比方: