写在前面
架构设计中,常常面对消息中间件的选型。那么,今天我们就来聊一下,分布式系统下消息中间件,到底是什么?核心组件包括什么?如何设计?又是如何保障分布式系统的稳定。
我们将从以下方面展开聊的内容:
- 什么是分布式消息中间件
- 协议
- 持久化
- 消息分发实现
- 高可用
- 高可靠
什么是分布式消息中间件
聊这个话题,首先需要,扯一下系统架构的历史以及演变。
简单来讲,我们系统架构设计的历史,是从单体架构,走向分布式架构。
单体架构,就是所有的服务模块都集中在一个应用中,由该应用直接访问数据库,完成业务逻辑。耦合度比较高。
分布式架构,按照模块拆分应用,前台系统按照业务逻辑调用相关后端应用,涉及到其他后台应用的,进行互相调用。由多系统协同完成业务逻辑。
传统的实现来说,分布式架构中,多个模块应用间调用采用Rpc或者Http等其他方式实现,但是这样还是增加了模块应用间的耦合,因此产出了一个中间件,用来沟通模块应用间的数据交换,这样就能够减少了模块间的耦合。
采用了消息中间件之后,系统发送消息,先存储在消息中间件,然后由消息中间件将消息分发到对应的业务模块应用。异步的方式,减少了耦合程度。
那么,我们就可以尝试的下定义了
消息中间件:
- 利用高效可靠的消息传递机制进行平台无关的数据交流;
- 基于数据通信,来进行分布式系统的集成
- 通过提供消息传递和消息排队模型,可以在分布式环境下扩展进程间的通信
由此可见常见应用常见场景:
跨系统的数据传递、高并发的流量削峰、数据异步处理等等
注:常见的消息中间件包括ActiveMQ、 RabbitMQ 、RocketMQ 、Kafka等
消息中间件核心设计
我们已经很清晰的知道,分布式消息中间件是个什么了,那么我们来尝试去分析下,一个消息中间件,是如何设计的?有什么必备的要求,才能成为一个消息中间件。了解这些,才能帮助我们更多的理解消息中间件在分布式系统中应用的意义。
那么,很明显,消息中间件本质上就是一种具备接受请求、保存数据、发送数据功能的网络应用,和一般的网络应用程序的区别在于,责任单一,主要负责数据的接受和传递,因此性能高于普通的应用程序。
在中间件设计时,经常用来描述的是生产者-消费者模式。那么对于,消息中间件,我们按照生产者-消费者模式进行设计,就能得到如下的设计:
以此为蓝图,去设计,就引出了考虑消息中间件的五大核心组成
- 协议
- 持久化机制
- 消息分发机制
- 高可用设计
- 高可靠设计
协议
消息中间件本身就是个完成数据交换的网络应用,那么必须有一个约定去沟通模块应用间的交流。
协议是计算机之间通信时共同遵从的一组约定,都遵守相同的约定,计算机之间才能相互交流。
是对数据格式和计算机之间交换数据时必须遵守的规则正式的描述。
协议三要素:
1)语法:即数据与控制信息的结构或格式
2)语义:即需要发出何种控制信息,完成何种动作以及做出何种响应
3)时序:即事件实现顺序的详细说明
常见的协议介绍
HTTP协议三要素举例:
语法:http规定了请求报文和响应报文的具体格式
语义:客户端主动发起的操作称为请求,比如get put post等
时序:一个请求对应一个响应
消息中间件常用的协议:OpenWire、AMQP、MQTT、Kafka、OpenMessage
那么为何不直接使用http协议?
主要考虑还是http的厚重,http的请求响应携带大量的信息,无疑增大了消息中间件的复杂程度。我们前边提到,消息中间件,就是一个最简单的网络应用,那么越简单性能越好。另外,一般来说http都是短连接,但是消息中间件一般都是场景下,属于长连接,所以http也不大合适。
OpenWire协议:目前主要是ActiveMQ中间件在用,今天我们不细展开,后续聊ActiveMQ时,我们再去聊
AMQP协议:(Advanced Message Queuing Protocol)是高级消息队列协议,于04年摩根大通集团联合其他公司共同设计。
特性:事务支持、持久化支持、出生于金融,在可靠性消息处理上具备天然的优势
目前,RabbitMQ ActiveMQ都在使用,协议具体实现根据各个中间件,或略有不同。
MQTT协议:(Message Queuing Telemetry Transport)消息队列遥测传输是IBM开发的一个即时通讯协议,物联网系统架构中的重要组成部分
特性:轻量、结构简单、传输快、没有事务支持、没有持久化相关设计
基于此,基本上应用在计算能力有限、网络低带宽、网络不稳定的场景
RabbitMQ、ActiveMQ支持该协议。
OpenMessaging协议:是近一两年由阿里发起,与雅虎、滴滴出行、Streamlio等公司共同参与创立的分布式消息中间件、流处理领域的应用开发标准。
是国内首个在全球范围内发起的分布式消息领域国际标准
特性:结构简单、解析快、支持事务、支持持久化
Kafka协议:基于TCP的二进制协议,消息内部通过长度来进行分隔,由一些基本数据类型组成
特性:结构简单、解析快、不支持事务、支持持久化
持久化
在消息中间件协议部分,可以看到,很多协议支持持久化的设计,那么持久化是什么?
简单来说,持久化,就是将数据存入磁盘,不是存在内存中,随着服务重启而消失,使得数据能够永久保存
如果没有持久化,当消息中间件挂掉就会发生数据丢失
完成持久化到磁盘之后,就能保存数据。
常见的持久化方式
ActiveMQ | RabbitMQ | Kafka | RocketMQ | |
文件系统 | 支持 | 支持 | 支持 | 支持 |
支持 | / | / | / |
消息分发
生产者生产消息到消息中间件,那么消费者如何进行消费,就涉及到消息分发的设计
一般来说,分为两部分
- 消息中间件进行数据消息推送
- 消费者从消息中间件拉取数据消息
类似于Git版本控制中的操作一样。
无论是推送还是拉取,都会涉及到一定的规则和策略,保证正确的消费者得到消费,那么就需要消息分发策略
为什么要有消息分发策略
我们需要订单系统收到消息,而其他的系统不应该消费消息,那么消息就要有分发策略
当我们消息进行消费失败,会涉及到消息回滚、消息重发等操作,那么也会需要分发策略,保证消息分发给对应的消费者
常用的消息中间件消息分发策略
ActiveMQ | RabbitMQ | Kafka | RocketMQ | |
发布订阅 | 支持 | 支持 | 支持 | 支持 |
轮询分发 | 支持 | 支持 | 支持 | / |
公平分发 | / | 支持 | 支持 | / |
重发 | 支持 | 支持 | / | 支持 |
消息拉取 | / | 支持 | 支持 | 支持 |
发布订阅策略是标准实现,轮徇分发、公平分发主要针对消费者集群时的策略,重发,是消息消费失败情况下的重试,消息拉取,即消费者pull操作。
高可用机制
处理完消息中间件的本身实现之后,要考虑在系统中集成时的高可用。
高可用性是指,产品在规定的条件和规定的时刻或者时间区间内处于可执行规定的功能状态能力
当业务量大时,一台消息中间件服务器可能无法满足要求,所以需要消息中间件集群部署,实现高可用。
常见的高可用集群实现
1)Master-slave主从共享数据部署方式
主从消息中间件共享数据
2)Master-slave主从同步部署方式
主从消息中间件之间会完整的同步消息
3)Broker-Cluster多主集群同步部署方式
多个主节点,可以同时消息写入
4)Broker-Cluster多主集群转发部署方式
消息中间件会转发请求或者数据到另外的消息中间件,消费者可以消费
5)Master-Slave与Broker-Cluster结合
后续在中间件详细的学习中,我们去了解具体的高可用实现方案
高可靠
高可靠,系统可以无故障的持续运行。比如一个系统从来不崩溃、报错,或者几率较低,那么就是高可靠
在高并发场景下,如果不能保证系统的高可靠,会造成巨大的损失。
保证消息中间件的高可靠性,可以从以下几个方面考虑:
消息传输可靠:通过协议来保证系统间数据解析的正确性
消息存储可靠:通过持久化来保证消息的存储可靠性
总结
我们今天聊了分布式消息中间件设计的前世今生,对于后续我们去了解分布式消息中间件的应用,具有很大的意义。