RabbitMQ学习笔记(一)
前言
学自学相伴
中间件
什么是中间件?
中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平台),但在这组中间件中必须要有一个通信中间件,即中间件=平台+通信,这个定义也限定了只有用于分布式系统中才能称为中间件,同时还可以把它与支撑软件和实用软件区分开来。
大白话:就是将一个企业中同时运行的多个不同的业务系统(这些系统可能基于不同的操作系统、不同的数据库、异构的网络环境)结合成一个有机地协同工作的整体,真正实现企业跨平台、分布式应用
举例来说,一个用Java开发的用户系统如果要与另一个Go开发的订单系统相结合,此时需要使用中间件来联通,那么此时中间件需要具备以下特点:
- 遵循某种相同的规范用以沟通通信
- 高可用
- 持久性
中间件技术举例
1. RMI
(Remote Method Invocations
, 远程调用)
2. Load Balancing
(负载均衡,将访问负荷分散到各个服务器中)
3. Transparent Fail-over
(透明的故障切换)
4. Clustering
(集群,用多个小的服务器代替大型机)
5. Back-end-Integration
(后端集成,用现有的、新开发的系统如何去集成遗留的系统)
6. Transaction
事务(全局/局部)全局事务(分布式事务)局部事务(在同一数据库联接内的事务)
7. Dynamic Redeployment
(动态重新部署,在不停止原系统的情况下,部署新的系统)
8. System Management
(系统管理)
9. Threading
(多线程处理)
10. Message-oriented Middleware
面向消息的中间件(异步的调用编程)
11. Component Life Cycle
(组件的生命周期管理)
12. Resource pooling
(资源池)
12. Security
(安全)
13. Caching
(缓存)
中间件优点
从非中间件开发者的角度来讲,中间件屏蔽了操作系统的复杂性,使开发者不必过多中间件需要遵循哪些协议(TCP/IP/UCP),不必过多关注操作系统的复杂性。同样屏蔽了应用程序间的局限性(可以使用java,也可以使用go,php),缩短开发周期,减少维护成本。
中间件使程序,架构变得更加优雅轻便
中间件知识图谱
消息中间件
消息中间件是一种接受数据,接受请求、存储数据、发送数据等功能的技术服务。 常见中间件:ActiveMQ、RabbitMQ、Kafka、RocketMQ等。
作用:
- 跨系统数据传递
- 高并发的流量削峰
- 数据的分发和异步处理
- 大数据分析与传递
- 分布式事务
生产者与消费者之间的数据传递,存储,分发消费,是否支持持久化 / 高可用 / 高可扩等都需要一个协议来进行统一的规范(在TCP/IP协议基础上构建自己的协议)
消息中间件的核心组成部分:
- 消息的协议
- 消息的持久化机制
- 消息的分发策略
- 消息的高可用,高可靠
- 消息的容错机制
单体架构和分布式架构
- 单体架构:所有功能整合在一个项目中
在企业开发的中,大部分的初期架构都采用的是单体架构的模式进行架构,而这种架构的典型的特点:就是把所有的业务和模块,源代码,静态资源文件等都放在一个工程中,如果其中的一个模块升级或者迭代发生一个很小变动都会重新编译和重新部署项目。 这种的架构存在的问题就是:
- 耦合度太高
- 运维的成本过高
- 不易维护
- 服务器的成本高
- 升级架构的复杂度也会增大
- 分布式架构:将一个项目的各个功能拆分为独立的服务
就是一个请求由服务器端的多个服务(服务或者系统)协同处理完成
和单体架构不同的是,单体架构是一个请求发起jvm调度线程(确切的是tomcat线程池)分配线程Thread来处理请求直到释放,而分布式是系统是:一个请求是由多个系统共同来协同完成,jvm和环境都可能是独立。分布式架构系统存在的特点和问题如下:
缺点:
- 学习成本高,技术栈过多
- 运维成本和服务器成本增高
- 人员的成本也会增高
- 项目的负载度也会上升
- 面临的错误和容错性也会成倍增加
- 占用的服务器端口和通讯的选择的成本高
- 安全性的考虑和因素逼迫可能选择RMI/MQ相关的服务器端通讯。
优点
- 服务系统的独立,占用的服务器资源减少和占用的硬件成本减少,确切的说是:可以合理的分配服务资源,不造成服务器资源的浪费
- 系统的独立维护和部署,耦合度降低,可插拔性
- 系统的架构和技术栈的选择可以变的灵活(而不是单纯的选择java)
- 弹性的部署,不会造成平台因部署造成的瘫痪和停服的状态。
消息队列协议
什么是协议?
- 计算机底层操作系统和应用程序通讯时共同遵守的一组约定,只有遵循共同的约定和规范,系统和底层操作系统之间才能相互交流。
- 和一般的网络应用程序的不同它主要负责数据的接受和传递,所以性能比较的高。
- 协议对数据格式和计算机之间交换数据都必须严格遵守规范。
消息中间件负责数据的传递,存储,和分发消费三个部分,数据的存储和分发的过程中肯定要遵循某种约定成俗的规范,到底是采用底层的TCP/IP,UDP协议还是其他的自己构建协议等。
这些约定成俗的规范就称之为:协议。
协议:是在tcp/ip协议基础之上构建的一种约定成俗的规范和机制、它的主要目的可以让客户端(应用程序 java,go)进行沟通和通讯。并且这种协议下规范必须具有持久性,高可用,高可靠的性能。
注意:所有的中间件技术都是基于tcp/ip协议基础上构建新的协议规范
网络协议三要素
- 语法 : 用户数据与控制信息的结构与格式,以及数据出现的顺序。
- 语义 : 解释控制信息每个部分的意义。它规定了需要发出何种控制信息,以及完成的动作,做什么响应。
- 时序 : 对事件发生顺序的详细说明。
比如说一个HTTP请求,语法指规定了请求报文和响应报文的格式,语义指客户端发出请求(get或post),然后响应,时序在这可以指先请求后响应
消息中间件采用的并不是http协议,常见的消息中间件协议有:OpenWire、AMQP、MQTT、Kafka,OpenMessage协议,那么问题来了:
为什么消息中间件不直接使用http协议呢?
1: 因为http请求报文头和响应报文头是比较复杂的,包含了cookie,数据的加密解密,状态码,响应码等附加的功能,但是对于一个消息而言,我们并不需要这么复杂,也没有这个必要性,它其实就是负责数据传递,存储,分发就行,一定要追求的是高性能。尽量简洁,快速。
2:大部分情况下http大部分都是短链接,在实际的交互过程中,一个请求到响应很有可能会中断,中断以后就不会就行持久化,就会造成请求的丢失。这样就不利于消息中间件的业务场景,因为消息中间件可能是一个长期的获取消息的过程,出现问题和故障要对数据或消息就行持久化等,目的是为了保证消息和数据的高可靠和稳健的运行。
AMQP协议
AMQP
:(全称:Advanced Message Queuing Protocol
) 是高级消息队列协议。
由摩根大通集团联合其他公司共同设计。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现有RabbitMQ等。
特性:
- 分布式事务支持
- 消息的持久化支持
- 高性能和高可靠的消息处理优势
支持者:RabbitMQ,ActiveMQ
MQTT协议
MQTT协议:(Message Queueing Telemetry Transport)消息队列是IBM开放的一个即时通讯协议,物联网系统架构中的重要组成部分。
特点:
- 轻量
- 结构简单
- 传输快,不支持事务
- 没有持久化设计
应用场景:
- 适用于计算能力有限
- 低带宽
- 网络不稳定的场景。
支持者:RabbitMQ,ActiveMQ
OpenMessage协议
近几年由阿里、雅虎和滴滴出行、Stremalio等公司共同参与创立的分布式消息中间件、流处理等领域的应用开发标准。
特点:
- 结构简单
- 解析速度快
- 支持事务和持久化设计。
支持者:Apache RocketMQ
Kafka协议
Kafka协议是基于TCP/IP的二进制协议。消息内部是通过长度来分割,由一些基本数据类型组成。
特点是:
- 结构简单
- 解析速度快
- 无事务支持
- 有持久化设计
支持者:Kafka
消息队列持久化
持久化:持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗的讲,就是瞬时数据(比如内存中的数据,是不能永久保存的)持久化为持久数据(比如持久化至数据库中,能够长久保存)。简单来说就是将数据存入磁盘,而不是存在内存中随服务器重启断开而消失,使数据能够永久保存。
- 常见持久化方式
ActiveMQ | RabbitMQ | RocketMQ | Kafka | |
---|---|---|---|---|
文件存储 | √ | √ | √ | √ |
数据库 | √ | ❌ | ❌ | ❌ |
消息的分发策略
MQ消息队列有如下几个角色
- 生产者
- 存储消息
- 消费者
生产者生成消息以后,MQ进行存储,消费者消费消息。、
消费者获取数据的方式一般为推(push)或者拉(pull)两种方式,
典型的git就有推拉机制,我们发送的http请求就是一种典型的拉取数据库数据返回的过程。而消息队列MQ是一种推送的过程,而这些推机制会适用到很多的业务场景也有很多对应推机制策略。
场景分析
- 比如我们在APP中下了一个订单,我们的系统和服务很多,我们如何得知这个消息被那个系统或者那些服务或者系统进行消费,那这个时候就需要一个分发的策略。这就需要消费策略。或者称之为消费的方法论
- 在发送消息的过程中可能会出现异常,或者网络的抖动,故障等等因为造成消息的无法消费,比如用户在下订单,消费MQ接受,订单系统出现故障,导致用户支付失败,那么这个时候就需要消息中间件就必须支持消息重试机制策略。也就是支持:出现问题和故障的情况下,消息不丢失还可以进行重发。
ActiveMQ | RabbitMQ | RocketMQ | Kafka | |
---|---|---|---|---|
发布订阅 | √ | √ | √ | √ |
轮询分发 | √ | √ | ❌ | √ |
公平分发 | ❌ | √ | ❌ | √ |
重发 | √ | √ | √ | ❌ |
消息拉取 | ❌ | √ | √ | √ |
消息队列高可用高可靠
高可用机制
高可用是指产品在规定的条件和规定的时刻或时间内处于可执行规定功能状态的能力。
当业务量增加时,请求也过大,一台消息中间件服务器的会触及硬件(CPU,内存,磁盘)的极限,一台消息服务器你已经无法满足业务的需求,所以消息中间件必须支持集群部署。来达到高可用的目的。
消息队列中的高可用有五种模式:
图片来自
集群模式1 - Master-slave主从共享数据
生产者将消费发送到Master节点写入消息存储,所有的主从节点都连接这个消息队列,共享这块数据区域。
在这其中,Master节点负责写入,一旦Master挂掉,slave节点继续服务。从而形成高可用,
集群模式2 - Master- slave主从同步
写入消息同样在Master主节点上,但是主节点会同步数据到slave节点形成副本,和zookeeper或者redis主从机制很类同。这样可以达到负载均衡的效果,如果消费者有多个,这样就可以去不同的节点消费,但是消息的拷贝和同步会暂用很大的带宽和网络资源。
集群模式3 - 多主集群同步
和方式二差别不大,但是它的写入可以往任意节点去写入。
集群模式4 - 多主集群转发(常用)
如果你插入的数据是broker-1中,元数据信息会存储数据的相关描述和记录存放的位置(队列)。
它会对描述信息也就是元数据信息就行同步,如果消费者在broker-2中进行消费,发现自己几点没有对应的消息,可以从对应的元数据信息中去查询,然后返回对应的消息信息,
场景:比如买火车票或者黄牛买演唱会门票,比如第一个黄牛有顾客说要买的演唱会门票,但是没有但是他会去联系其他的黄牛询问,如果有就返回
元数据:元数据(metadata)是关于数据的组织、数据域及其关系的信息,简言之,元数据就是描述数据的数据。
拿书来举例,元数据就是标题,作者姓名,出版社和版权信息,封皮背面的描述信息,目录,索引,页码;在数据中,元数据就是标题和描述,标签和分类,创建时间创建人与更新时间更新人
集群模式5 Master-slave与Breoker-cluster组合
实现多主多从的热备机制来完成消息的高可用以及数据的热备机制,在生产规模达到一定的阶段的时候,这种使用的频率比较高。
总结起来就三种
- 消息共享
- 消息同步
- 元数据共享
高可靠机制
所谓高可用是指:是指系统可以无故障低持续运行,比如一个系统突然崩溃,报错,异常等等并不影响线上业务的正常运行,出错的几率极低,就称之为:高可靠。
在高并发的业务场景中,如果不能保证系统的高可靠,那造成的隐患和损失是非常严重的。
如何保证中间件消息的可靠性呢?可以从两个方面考虑:
- 消息的传输:通过协议来保证系统间数据解析的正确性。
- 消息的存储可靠:通过持久化来保证消息的可靠性。