什么是消息中间件
Message Queue,消息队列是基础数据结构中“先进先出”的一种数据结构。一般用来解决应用解耦,异步消息,流量削峰等问题,实现高性能,高可用,可伸缩和最终一致性架构。实现消息队列的框架通常被称为“消息中间件”。
主要特点:
1. 分布式:消息中间件都是分布式的,因此才可以提供异步、解耦等功能。
2. 可靠性:基于消息的通信是可靠的,消息不会丢失。大多数消息中间件都提供将消息持久化到磁盘的功能。
3. 异步:通过消息中间件,可将远程同步调用拆解成为异步调用。对于不需要获取远程调用结果的应用场景来说,性能提升明显。
4. 松耦合:消息直接由中间件存储和分发。消息生产者只需关注如何将消息发送给消息中介服务器;消费者只需关注如何从中介服务器订阅。生产者和消费者之间是完全解耦的,不需要知道彼此的存在。
5. 事件驱动:可以将复杂的应用系统重构成为事件驱动的系统。事件溯源(Event Sourcing),表示一个对象从创建到消亡,会经过的多种状态。如果把对象的状态变化都存储下来,不但可以根据状态变化记录获取对象的当前状态,也可以回溯对象的变化过程。消息中间件能很好地支持这样的系统设计方式,将触发对象状态变化的事件放入消息队列。
消息中间件的组成
- Broker:消息服务器,作为server提供消息核心服务
- Producer:消息生产者,业务的发起方,负责生产消息传输给broker,
- Consumer:消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理
- Topic:主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的 广播
- Queue:队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收
Message:消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输
消息中间件的两种模式
p2p模式 (点对点)
-
P2P模式
P2P模式包含三个角色:消息队列(Queue),发送者(Sender),接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到他们被消费或超时。
P2P的特点:
每个消息只有一个消费者(Consumer)(即一旦被消费,消息就不再在消息队列中)
发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行它不会影响到消息被发送到队列
接收者在成功接收消息之后需向队列应答成功。如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式。Pub/Sub模式
Pub/Sub模式包含三个角色:主题(Topic),发布者(Publisher),订阅者(Subscriber) 。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
Pub/Sub的特点: 每个消息可以有多个消费者
- 发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
- 为了消费消息,订阅者必须保持运行的状态。
如果希望发送的消息可以不被做任何处理、或者只被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型。
消息中间件相关概念
消息中间概述
关注数据的发送和接受,利用高效可靠的异步消息传递机制集成了分布式系统
什么是JMS?
Java消息服务(Java Message Service),是一个Java平台中关于面向消息的中间件的API,用于两个应用程序之间或者分布式 系统中发布消息,进行异步通信。
什么是AMQP?
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。 基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有 RabbitMQ等。
JMS和AMQP的比价
MQ协议
协议是什么
协议是计算机之间通信时共同遵循的一组约定,遵循相同的约定,计算机之间才能交流。
协议是对数据格式和对交换数据时必须遵守的规则的正式描述,简单来说协议就是规则。
协议三要素
- 语法:即数据与控制信息的结构或格式
- 语义:即需要发出何种控制信息、完成何种动作及做出何种反应
- 时序:即事件实现顺序的详细说明
以 HTTP 协议为例
- 语法:HTTP 规定了请求报文和响应报文的具体格式
- 语义:客户端主动发起的操作成为请求
- 时序:一个请求对应一个响应
消息中间件常用的协议
OpenWire、AMQP、MQTT、Kafka、OpenMessage
思考:为什么消息中间件不直接使用 HTTP 协议?协议介绍
AQMP 协议
AMQP(Advanced Message Queuing Protocol)是高级消息队列协议
04年 JpMorgan Chase(摩根大通集团)联合其他公司共同设计。特性:
事务支持、持久化支持,出生于金融行业,在可靠性消息处理上有天然的优势。
RabbitMQ、ActiveMQ 实现了此协议MQTT 协议
MQTT(Message Queuing Telemetry Teansport)消息队列遥测传输
是 IBM 开发的一个即使通讯协议,物联网系统架构中的重要组成部分。特性:
轻量、结构简单、传输快、没有事务支持、没有持久化相关设计。应用场景:
适用于计算能力有限、低带宽、网络不稳定的场景。
RabbitMQ、ActiveMQ 实现了此协议OpenMessage 协议
OpenMessage 是近一两年由阿里发起,与雅虎、滴滴出行、Streamlio 等公司共同参与创立的分布式消息中间件、流处理领域的应用开发标准。特性:
结构简单、解析快、有事务设计、有持久化设计
RocketMQ 实现了此协议Kafka 协议
Kafka 协议是基于 TCP 的二进制协议。消息内部是通过长度来分隔,由一些基本数据类型组成。特性:
结构简单、解析快、无事务设计、有持久化设计
Kafka 实现了此协议持久化
简单来说就是将数据存入磁盘,而不是存在内存中随服务重启而消失,使数据能够永久保存叫做持久化。
常用消息中间件支持的持久化方式
- | ActiceMQ | RabbitMQ | Kafka | RocketMQ |
---|---|---|---|---|
文件系统 | 支持 | 支持 | 支持 | 支持 |
数据库 | 支持 | / | / | / |
消息分发
常用消息中间件的分发策略
- | ActiveMQ | RabbitMQ | Kafka | RocketMQ |
---|---|---|---|---|
发布订阅 | 支持 | 支持 | 支持 | 支持 |
轮询分发 | 支持 | 支持 | 支持 | / |
公平分发 | / | 支持 | 支持 | / |
重发 | 支持 | 支持 | / | 支持 |
消息拉取 | / | 支持 | 支持 | 支持 |
- 发布订阅:当多个系统连接到消息中间件时,通过发布订阅知道消息是要发送给谁。
- 轮询分发、公平分发:当有多个节点有相同的订阅,是大家公平的接收,还是通过权重计算分发的对象。
- 重发:当由于系统原因导致异常,消息中间件可以重发这条数据
- 消息拉取:消息是主动分发,还是客户端主动拉取数据
高可用
高可用性,指的是产品在规定的条件和规定的时刻或时间区间内,处于可执行规定状态功能的能力。
当业务量大时,一台消息中间件服务器可能无法满足需求,所以需要消息中间件能够集群部署,来达到高可用目的。Master-Slave 主从共享数据部署方式
和数据库主从类似,但这里是共享数据,读取同一份数据源,当一台挂了,就切换到其他服务器,但数据还是同一份
Master-Slave 主从同步部署方式
Broker-Cluster 多主集群同步部署方式
多个服务器可以同时接收不同消费者的请求,数据会在每个服务器上备份
Broker-Cluster 多主集群转发部署方式
服务器可以将请求转发给其他服务器,可以选择转发数据或者转发请求,若转发请求的话,则所有服务器公用同一份数据。
Master-Slave 与 Broker-Cluster 结合
主流的消息中间件?
当前业界比较流行的开源消息中间件包括:ActiveMQ、RabbitMQ、RocketMQ、Kafka等。Redis在某种程度上也可以是实现类似 “Queue” 和“ Pub/Sub” 的机制,严格意义上不算消息中间件。
RabbitMQ
RabbitMQ 开始是用在电信业务的可靠通信的,也是少有的几款支持AMQP协议的产品之一。
优点:
- 轻量级,快速,部署使用方便
- 支持灵活的路由配置。RabbitMQ中,在生产者和队列之间有一个交换器模块。根据配置的路由规则,生产者发送的消息可以发送到不同的队列中。路由规则很灵活,还可以自己实现。
- RabbitMQ的客户端支持大多数的编程语言。
缺点:
- 如果有大量消息堆积在队列中,性能会急剧下降
- RabbitMQ的性能较差,每秒处理几万到几十万的消息。如果应用要求高的性能,不要选择RabbitMQ。
RabbitMQ是Erlang开发的,功能扩展和二次开发代价很高。
RocketMQ
RocketMQ 是一个开源的消息队列,使用 java 实现。借鉴了 Kafka 的设计并做了很多改进。
优点:RocketMQ 主要用于有序,事务,流计算,消息推送,日志流处理,binlog分发等场景。经过了历次的双11考验,性能,稳定性可可靠性没的说。
- RocketMQ 几乎具备了消息队列应该具备的所有特性和功能。
- java 开发,阅读源代码、扩展、二次开发很方便。
- 对电商领域的响应延迟做了很多优化。在大多数情况下,响应在毫秒级。如果应用很关注响应时间,可以使用RocketMQ。
- 性能比RabbitMQ高一个数量级,每秒处理几十万的消息。
缺点:
-
Kafka
Kafka的可靠性,稳定性和功能特性基本满足大多数的应用场景。跟周边系统的兼容性是数一数二的,尤其是大数据和流计算领域,几乎所有相关的开源软件都支持Kafka。Kafka是Scala和Java开发的,对批处理和异步处理做了大量的设计,因此Kafka可以得到非常高的性能。它的异步消息的发送和接收是三个中最好的,但是跟RocketMQ拉不开数量级,每秒处理几十万的消息。如果是异步消息,并且开启了压缩,Kafka最终可以达到每秒处理2000w消息的级别。
优点: 支持多个生产者和消费者
- 支持broker的横向拓展
- 副本集机制,实现数据冗余,保证数据不丢失
- 通过topic将数据进行分类
- 通过分批发送压缩数据的方式,减少数据传输开销,提高吞高量
- 支持多种模式的消息
- 基于磁盘实现数据的持久化
- 高性能的处理信息,在大数据的情况下,可以保证亚秒级的消息延迟
- 一个消费者可以支持多种topic的消息
- 对CPU和内存的消耗比较小
- 对网络开销也比较小
- 支持跨数据中心的数据复制
- 支持镜像集群
缺点:
- 由于是批量发送,所以数据达不到真正的实时
- 对于mqtt协议不支持
- 不支持物联网传感数据直接接入
- 只能支持统一分区内消息有序,无法实现全局消息有序
- 监控不完善,需要安装插件
- 需要配合zookeeper进行元数据管理
- 会丢失数据,并且不支持事务
- 可能会重复消费数据,消息会乱序,可用保证一个固定的partition内部的消息是有序的,但是一个topic有多个partition的话,就不能保证有序了,需要zookeeper的支持,topic一般需要人工创建,部署和维护一般都比mq高。、
引入MQ优缺点
优点:
- 解耦
- 消峰
缺点
- 系统总体复杂性会提高
- 系统总体可用性会降低
- MQ自身的一系列问题
- 消息丢失
- 分布式数据一致性问题
- 消息消费顺序
- 消息积压
- 消息重复消费,幂等性