1、消息队列(MQ)
简介
消息队列的本质是一种队列,而队列的主题携带了一定的message也就是消息,这些消息是我们队列要处理时使用到的数据或要处理的对象,甚至其他任何信息。
消息队列有三个应用场景比较经典
1、流量削峰:在流量峰值时,将请求存在队列中,然后在流量谷值时将流量释放,从而让瞬时流量大的峰值点舒缓至谷值。
2、异步处理:串行模式下可能会出现阻塞等对用户不友好的现象,为我们可以将请求存放在队列中,然后通过一定机制逐个处理,而不是与主系统同步执行。
3、应用解耦:将系统中原有的耦合请求链路缓存到队列中,两级系统间加入消息中间件,从而实现解耦,如此一来上游系统崩溃的情况下,下游系统依旧可以运作。
JMS:JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供支持。我们可以简单的理解:两个应用程序之间需要进行通信,我们使用一个JMS服务,进行中间的转发,通过JMS 的使用,我们可以解除两个程序之间的耦合。
JMS有两种消息模型:
(1)、Point-to-Point Messaging Domain(点对点通信模型)
(2)、Publish/Subscribe Messaging Domain(发布/订阅通信模型)
JMS如何使用:
(1)、Connection Factories,分别有QueueConnectionFactory和TopicConnectionFactory两种
(2)、Destination,目的地指明消息被发送的目的地以及客户端接收消息的来源。JMS使用两种目的地,队列和话题
(3)、Connection,Connection表示在客户端和JMS系统之间建立的链接(对TCP/IP socket的包装),Connection也有两种类型:QueueConnection和TopicConnection
(4)、Session,Session 是我们对消息进行操作的接口,可以通过session创建生产者、消费者、消息等
(5)、Producter,消息生产者由Session创建,用于往目的地发送消息。
(6)、Consumer,消息消费者由Session创建,用于接收被发送到Destination的消息
7)、MessageListener,消息监听器。如果注册了消息监听器,一旦消息到达,将自动调用监听器的onMessage方法。
AMQP :Advanced Message Queue,高级消息队列协议。它是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。
AMQP 中的消息路由
AMQP 中消息的路由过程和 Java 开发者熟悉的 JMS 存在一些差别,AMQP 中增加了 Exchange 和 Binding 的角色。生产者把消息发布到 Exchange 上,消息最终到达队列并被消费者接收,而 Binding 决定交换器的消息应该发送到那个队列
Exchange分发消息时根据类型的不同分发策略有区别,目前共四种类型:direct、fanout、topic、headers 。headers 匹配 AMQP 消息的 header 而不是路由键,此外 headers 交换器和 direct 交换器完全一致,但性能差很多,目前几乎用不到了,所以直接看另外三种类型
1、direct
消息中的路由键(routing key)如果和 Binding 中的 binding key 一致, 交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消息,不会转发“dog.puppy”,也不会转发“dog.guard”等等。它是完全匹配、单播的模式。
2、fanout
每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout 交换器不处理路由键,只是简单的将队列绑定到交换器上,每个发送到交换器的消息都会被转发到与该交换器绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。fanout 类型转发消息是最快的。
3、topic
topic 交换器通过模式匹配分配消息的路由键属性,将路由键和某个模式进行匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号“”。#匹配0个或多个单词,匹配不多不少一个单词。
2、MQ的分类
Active MQ
优点,单机吞吐量大,时效性ms级,可用性高,基于主从架构实现高可用,很难丢失消息。
缺点,官方社区维护越来越少。
kafka
大数据的杀手锏,谈到大数据领域内的消息传输,kafka是最可靠的消息中间件,具有百万计tps的吞吐量。
优点,性能卓越,吞吐量大,且有优秀的第三方管理界面
缺点,kafka单机超过64个队列、分区,load会发生明显飙高现象,社区更新较慢。
Rocket MQ
阿里巴巴的开源产品,java实现。
优点,单机吞吐量达到十万级,分布式架构下,消息可以做到0丢失。
缺点,支持客户端语言不多,社区活跃度不高,没有实现JMS等接口,需要额外代码实现。
Rabbit MQ
2007年基于erlang语言开发,高并发,性能好,吞吐量到达万级,社区完善,跨平台,支持多语言。缺点是商业版本收费。
3、Rabbit MQ 简介
RabbitMQ 最初起源于金融系统,用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。具体特点包括:
1、可靠性(Reliability)
2、RabbitMQ 使用一些机制来保证可靠性,如持久化、传输确认、发布确认。
3、灵活的路由(Flexible Routing)
4、在消息进入队列之前,通过 Exchange 来路由消息的。对于典型的路由功能,RabbitMQ 已经提供了一些内置的 Exchange 来实现。针对更复杂的路由功能,可以将多个 Exchange 绑定在一起,也通过插件机制实现自己的 Exchange 。
5、消息集群(Clustering)
6、多个 RabbitMQ 服务器可以组成一个集群,形成一个逻辑 Broker 。
7、高可用(Highly Available Queues)
8、队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
9、多种协议(Multi-protocol)
10、RabbitMQ 支持多种消息队列协议,比如 STOMP、MQTT 等等。
11、多语言客户端(Many Clients)
12、RabbitMQ 几乎支持所有常用语言,比如 Java、.NET、Ruby 等等。
13、管理界面(Management UI)
14、RabbitMQ 提供了一个易用的用户界面,使得用户可以监控和管理消息 Broker 的许多方面。
15、跟踪机制(Tracing)
16、如果消息异常,RabbitMQ 提供了消息跟踪机制,使用者可以找出发生了什么。
17插件机制(Plugin System)RabbitMQ 提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。
工作原理:
组成部分说明:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。
Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
RabbitMQ 会始终记录以下四种类型的内部元数据:
队列元数据:包括队列名称和它们的属性,比如是否可持久化,是否自动删除
交换器元数据:交换器名称、类型、属性
绑定元数据:内部是一张表格记录如何将消息路由到队列
vhost 元数据: 为 vhost 内部的队列、交换器、绑定提供命名空间和安全属性
在单一节点中,RabbitMQ 会将所有这些信息存储在内存中,同时将标记为可持久化的队列、交换器、绑定存储到硬盘上。存到硬盘上可以确保队列和交换器在节点重启后能够重建。而在集群模式下同样也提供两种选择:存到硬盘上(独立节点的默认设置),存在内存中。
Rabbit MQ的消息持久化:
如果我们希望即使在RabbitMQ服务重启的情况下,也不会丢失消息,我们可以将Queue与Message都设置为可持久化的(durable),这样可以保证绝大部分情况下我们的RabbitMQ消息不会丢失。当然还是会有一些小概率事件会导致消息丢失。
1、队列持久化需要在声明队列时添加参数 durable=True,这样在rabbitmq崩溃时也能保存队列
2、仅仅使用durable=True ,只能持久化队列,不能持久化消息
3、消息持久化需要在消息生成时,添加参数 properties=pika.BasicProperties(delivery_mode=2)4、路由的持久化通过 autoDelete属性控制