MQ的基本概念
MQ全称Message Queue(消息队列),是在消息的传输过程中保存的消息的容器。多用于分布式系统之间进行通信。
MQ的优势
- 应用解耦:使用MQ使得应用间解耦,提升容错性和可维护性。
- 异步提速:采用异步的方式提升用户体验和系统吞吐量
- 削峰填谷:使用MQ之后,高峰产生的数据会被积压在MQ中,这样一来,高峰就被“削”掉了,但因为消息的积压,在高峰过后的一段时间,消费消息的速度还是会维持在比较高的水平,直到消费完积压的消息,这就叫做“填谷”。
MQ的劣势:
- 系统的可用性降低:系统引入的外部依赖越多,系统稳定性越差,一旦MQ宕机,就会对业务造成影响。
- 系统复杂度提高:MQ的引入大大增加了系统的复杂度,以前系统间是同步的远程调用,现在是通过MQ进行异步调用。
常见的MQ产品
RabbitMQ简介
RabbitMQ采用Erlang语言开发,Erlang语言由Ericson设计,专门为开发高并发和分布式系统的一种语言,在电信领域使用广泛。
RabbitMQ基础架构:
RabbitMQ提供了6中工作模式:简单模式、work queues、Publish/Subscribe发布与订阅模式、Routing路由模式、Topics主题模式、RPC远程调用模式。
RabbitMQ中的相关概念:
- Borker:接收和分发消息的应用,RabbitMQ Server就是Message Broker
- Virtual host:出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,
Broker:接收和分发消息的应用,RabbitMQ Server就是 Message Broker
.Virtual host:出于多租户和安全因素设计的,把AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等
Connection: publisher / consumer 和broker之间的TCP连接
Channel:如果每一次访问RabbitMQ都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也较低。Channel是在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id 帮助客户端和message broker识别channel,所以channel之间是完全隔离的。Channel 作为轻量级的 Connection极大减少了操作系统建立TCP
connection的开销。
Exchange:message到达broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到queue中去。常用的类型有:direct(point-to-point),topic(publish-subscribe)and fanout(multcast)
Queue:消息最终被送到这里等待consumer取走
Binding:exchange和queue之间的虚拟连接,binding中可以包含routing key。Binding信息被保存到exchange中的查询表中,用于message的分发依据
RabbitMQ的6种工作模式
- helloword:入门程序
P:生产者,也就是要发送消息的程序
C:消费者,消息的接收者,会一直等待消息到来
queue:消息队列,图中红色部分。类似一个邮箱,可以缓存消息;生产者向其中投递消息,消费者丛中获取消息。 - Work queues工作队列模式
Work Queues:与入门程序的简单模式相比,多了一个或一些消费端,多个消费端共同消费同一个队列中的消息。
应用场景:对于任务过重或任务较多情况使用工作队列可以提高任务处理的速度。在一个队列中如果有多个消费者,那么消费者之间对于同一个消息得到关系是竞争的关系。 - Pub/Sub订阅模式
P:生产者,也就是要发送消息的程序,但是不会再发送到队列中,而是发给X(交换机)
C:消费者,消息的接收者,会一直等待消息的到来
Queue:消息队列,接收消息、缓存消息。
Exchange:交换机(X)。一方面,接收生产者发送的消息。另一方面,知道如何处理消息,例如递交给某个特别队列、递交给所有队列】或是将消息丢弃。到底如何操作,取决于Exchange的类型。Exchange有常见以下的3种类型:
Fanout:广播,将消息交给所有绑定到交换机的队列
Direct:定向,把消息交给符合指定rounting key的队列
Topic:统配符,把消息交给符合rounting pattern(路由模式)的队列
Exchange只负责转发消息,不具备存储消息的能力,因此如果没有任何队列与Exchange绑定,或者没有符合路由规则的队列,那么消息将会丢失。
使用场景:发布订阅模式因为所有消费者获得相同的消息,所以特别适合“数据提供商与供应商”。 - Rounting路由模式:
队列与交换机的绑定,不能是任意绑定了,而是要指定一个Rounting key(路由key)
消息的发送方在向Exchange发送消息时,也必须指定消息的Rounting key
Exchange不再把消息交给每一个绑定的队列,而是根据消息的Rounting Key进行判断,只有队列的Rounting key与消息的Rounting key完全一致,才会接收到消息
P:生产者,向Exchange发送消息,发送消息时,会指定一个Rounting key
X:Exchange(交换机),接收生产者的消息,然后把消息递交给与rounting key完全匹配的队列
C1:消费者,其所在队列指定了需要rounting key为error的消息
C2:消费者,其所在队列指定了需要rounting key为info、error、warning的消息
Rounting模式要求队列在绑定交换机时要指定rounting key,消息会转发到符合rounting key的队列。 - Topic通配符模式:
Topic类型与Direct相比,都是可以根据Rounting key把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Rounting key的时候使用通配符。
Rounting key一般都是有一个或多个单词组成,多个单词之间以“.”分割,如item.insert
通配符规则:#匹配一个或多个词,*匹配一个词
RabbitMQ消息确认机制
RabbitMQ提供了监听器(listener)来接收消息投递的状态
消息确认涉及两种状态:Confirm与Return
Confirm代表生产者将消息送到Broker时的状态,后续会出现两种情况:
- ack代表Broker已经将数据接收。
- nack代表Broker拒收消息。原因有多种,队列已满,限流,IO异常。。。。
Return代表消息被Broker正常接收(ack)后,消息被退回给生产者。
- 上面的两种状态只代表生产者与Broker之间消息投递的情况。与消费者是否接收/确认消息无关。