前言:在程序猿的日常工作中, 经常会提到中间件,然而大家对中间件的理解并不一致,导致了一些不必要的分歧和误解。“中间件”一词被用来描述各种各样的软件产品,在不同文献中有着许多不同的中间件定义,包括操作系统(和/或网络)和应用程序之间的软件层,以及两个应用程序之间的“粘合剂”。它也被描述为一种重要的集成工具,或支持与分布式软件的模块化连接。一般而言中间件和框架的区别是,中间件是独立运行的用于处理某项专门业务的CS程序,会有配套的客户端和服务端,框架虽然也是处理某个专门业务的但是它不是独立程序,是寄宿在宿主程序进程内的一套类库。
一、中间件的概念
由于应用软件是在系统软件基础上开发和运行的,而系统软件又有多种,如果每种应用软件都要提供能在不同系统上运行的版本,开发成本将大大增加。因而出现了一类称为“中间件” (Middleware) 的软件,它们作为应用软件与各种操作系统之间使用的标准化编程接口和协议,可以起承上启下的作用,使应用软件的开发相对 独立于计算机硬件和操作系统,并能在不同的系统上运行,实现相同的应用功能。中间件是基础软件的一大类,属于可复用软件的范畴。顾名思义,中间件处在操作系统、网络和数据库之上, 应用软件的下层,如图所示。也有人认为中间件应该属于操作系统中的一部分。
中间件从诞生到现在,虽然仅有 10 多年时间,但发展极其迅速,是有史以来发展最快的软件产品,但在技术上还处于成长阶段,还没有统一的标准和模型,通常都是用 C++ 语言以面向对象的技术来实现的,但是它的特性已超出面向对象的表达能力,由于它属于可重用构件,目前趋向于用构件技术来实现。然而,中间件要涉及软件的所有标准 、 规范和技术,它有更多的内涵,因为它包括平台功能,自身具有自治性 、 自主性 、 隔离性 、 社会化 、 激发性 、 主动性 、 并发性 、 认识能力等特性,是近似于 Agent (代理)的结构。
1.1、中间件特点
-
满足大量应用的需要;
-
运行于多种硬件和 OS 平台;
-
支持分布计算,提供跨网络、硬件和 OS 平台的透明性的应用或服务的交互;
-
支持标准的协议;
-
支持标准的接口。
1.2、中间件的十大优越性
世界著名的咨询机构 Standish Group 在一份研究报告中归纳了:
-
缩短应用的开发周期;
-
节约应用的开发成本;
-
减少系统初期的建设成本;
-
降低应用开发的失败率;
-
保护已有的投资;
-
简化应用集成;
-
减少维护费用;
-
提高应用的开发质量;
-
保证技术进步的连续性;
-
增强应用的生命力。
具体来说,首先,中间件屏蔽了底层操作系统的复杂性,使程序开发人员面对一个简单而统一的开发环境,减少了程序设计的复杂性,将注意力集中在自己的业务上,不必再为程序在不同系统软件上的移植而重复工作,从而大大减少了技术上的负担。中间件带给应用系统的,不只是开发的简便 、 开发周期的缩短,也有系统的维护 、 运行和管理的工作量的减少,还减少了计算机总体费用的投入 。Standish 的调查报告显示,由于采用了中间件技术,应用系统的总建设费用可以减少 50% 左右。在网络经济 、 电子商务大发展的今天,从中间件获得利益的不只是 IT 厂商, IT 用户也同样是赢家,并且是更有把握的赢家。
其次,中间件作为新层次的基础软件,其重要作用是将不同时期 、 在不同操作系统上开发的应用软件集成起来,彼此无缝地整体协调工作,这是操作系统 、 数据库管理系统本身做不了的。中间件的这一作用,使得在技术不断发展之后,人们以往在应用软件上的劳动成果仍然物有所用,节约了大量的人力 、 财力投入。
最后,由于标准接口对于可移植性和标准协议对于互操作性的重要性,中间件已成为许多标准化工作的主要部分。对于应用软件开发,中间件远比操作系统和网络服务更为重要,中间件提供的程序接口定义了一个相对稳定的高层应用环境,不管底层的计算机硬件和系统软件怎样更新换代,只要将中间件升级更新,并保持中间件对外的接口定义不变,应用软件几乎不需任何修改,从而节省了企业在应用软件开发和维护中的重大投资。
1.3、中间件用途
-
提供工具和函数以简化复杂应用程序的开发。
-
提供高级抽象和接口,以促进应用程序的集成、重用和开发。
-
隐藏底层平台和操作环境的异构性。
-
隐藏基础环境中的分发机制和通信细节。
-
促进基础设施的不同分布式组件之间的通信。
-
为不同应用程序所需的通用功能提供共同服务,以减少开发工作和避免服务重复。
-
提供一个公共体系结构来添加新的服务和特性,而不必更改应用程序。
-
提供增值特性和非功能特性,如安全性、可靠性和 QoS。
-
提供必要的工具,以增强分布式应用程序的性能并提高其稳定性和可伸缩性。
二、中间件分类
按照中间件在分布式系统中承担的职责不同,可以划分以下几类中间件产品。
1)通信处理(消息)中间件
正如,人们通过安装红绿灯,设立交通管理机构,制定出交通规则,才能保证道路交通 畅通一样,在分布式系统中,人们要建网和制定出通信协议,以保证系统能在不同平台之间 通信,实现分布式系统中可靠的、高效的、实时的跨平台数据传输,这类中间件称为消息中间 件,也是市面上销售额最大的中间件产品,目前主要产品有BEA 的 eLink、IBM 的 MQSeries、 TongLINK 等。实际上, 一般的网络操作系统如Windows已包含了其部分功能。
2)事务处理(交易)中间件
正如城市交通中要运行各种运载汽车,以此来完成日常的运载工作,同时随时监视汽车的 运行,在出现故障时及时排堵保畅。在分布式事务处理系统中,经常要处理大量事务,特别是 OLTP中,每项事务常常要多台服务器上的程序按顺序协调完成, 一旦中间发生某种故障,不但 要完成恢复工作,而且要自动切换系统保证系统永不停机,实现高可靠性运行。要使大量事务 在多台应用服务器上能实时并发运行,并进行负载平衡的调度,实现与昂贵的可靠性机和大型 计算机系统的同等功能,为了实现这个目标,要求中间件系统具有监视和调度整个系统的功能。 BEA 的 Tuxedo 由此而闻名,它成为增长率最高的厂商。
3)数据存取管理中间件
在分布式系统中,重要的数据都集中存放在数据服务器中,它们可以是关系型的、复合文 档型、具有各种存放格式的多媒体型,或者是经过加密或压缩存放的,该中间件将为在网络上 虚拟缓冲存取、格式转换、解压等带来方便。
4)Web服务器中间件
浏览器图形用户界面已成为公认规范,然而它的会话能力差,不擅长做数据的写入任务, 受HTTP 协议的限制多等,就必须对其进行修改和扩充,因此出现了Web 服务器中间件,如 SilverStream 公司的产品。
5)安全中间件
一些军事、政府和商务部门上网的最大障碍是安全保密问题,而且不能使用国外提供的安 全措施(如防火墙、加密和认证等),必须用国产产品。产生不安全因素是由操作系统引起的, 但必须要用中间件去解决,以适应灵活多变的要求。
6)跨平台和架构的中间件
当前开发大型应用软件通常采用基于架构和构件技术,在分布式系统中,还需要集成各 结点上的不同系统平台上的构件或新老版本的构件,由此产生了架构中间件。功能最强的是 CORBA, 可以跨任意平台,但是其过于庞大;JavaBeans 较灵活简单,很适合用于浏览器,但运 行效率有待改善; COM+ 模型主要适合Windows 平台,已在桌面系统广泛使用。由于国内新建 系统多基于UNIX (包括Linux) 和 Windows, 因此,针对这两个平台建立相应的中间件市场相 对要大得多。
7)专用平台中间件
专用平台中间件为特定应用领域设计领域参考模式,建立相应架构,配置相应的构件库和 中间件,为应用服务器开发和运行特定领域的关键任务(如电子商务、网站等)。
8)网络中间件
它包括网管、接入、网络测试、虚拟社区和虚拟缓冲等,也是当前最热门的研发项目。
三、中间件在微服务中的应用场景
微服务的建设中实现远程调用只是实现了20%的工作量(但是确实满足了80%的需求)。服务管理治理这块有大量的工作要做。这也就是实现自己RPC框架的好处,这是第一步,有了这第一步让数据流过我们自己的框架以后我们接可以做更多的事情,比如:
-
服务发现和注册。查看服务的注册情况,服务手动上线下线,集群切换,压力分配干预。
-
配置管理。配置服务端客户端线程池和队列的配置,超时配置等等。当然,这个也可以在配置系统中进行。
-
全链路监控。能否记录整个微服务调用链路的情况,并且查看这个调用链。
-
熔断限流。熔断和进行并发限流配置,服务权限黑白名单配置,安全方面的配置(信息加密,日志脱敏等)。
-
Service Store的概念。服务发布需要满足一定要求,有文档(比如可以通过注解方式在代码注释里提供),有信息(开发负责人、运维负责人,服务类型,提供的能力),满足要求后就可以以类似于苹果App Store发布程序的方式发布服务,这样我们就可以在统一的平台上查看服务的维护信息和文档。
-
版本控制调用统计。对服务进行灰度升级,按版本路由,不同版本调用分析等等。类似于一些应用统计平台提供的功能(友盟、TalkingData)。
下图绿色部分代表了框架,红色部分代表了管理系统,紫色部分代表了中间件。本文会着重介绍管理系统和中间件部分。
(1)服务管理
服务能调用通是第一步,随着服务数量变多,部署方式的复杂化,依赖关系复杂化,版本的迭代,API的变更,开发人员和架构师其实急需有一套地图能够对服务能力的全貌进行整体的了解,运维也需要有系统能对服务进行观察和调配。服务治理的部分完全可以以iOS那套(开发符合时候需要符合标准+发布的时候需要有流程)方式来运作,常见的服务发现与注册有阿里的Nacos和 Netflix 公司的Eureka。
(2)配置管理
要实现一个功能完善的配置系统工作量还是相当大的,一个优秀的功能强大的配置系统可以节省很多开发的工作量,因为可配置部分的功能基本就是由配置系统直接实现了,无需在数据库中在搞大量的XXConfig表(不夸张的说,很多业务系统40%的工作量在这个上面,不但需要做这些配置表还需要配以配置后台)
比较知名的分布式配置服务和管理系统有阿里的Nacos和携程的apollo对于比较大型的互联网项目来说,因为业务繁杂,需求多变,往往各种系统都会有大量的配置,覆盖几个方面:
-
针对系统内部技术层面的各种配置,各种池的大小、 队列的大小、日志级别、各种路径、批次大小、处理间隔、重试次数、超时时间等。
-
针对业务运营层面的各种配置,活动的周期奖励、黑白名单、弹窗、广告位等。
-
针对运维和发布层面的配置,灰度名单、注册中心地址、数据库地址、缓存地址、MQ地址等
(3)全链路监控
开源的实现有https://github.com/dianping/cat以及https://github.com/naver/pinpoint(上图)等等。对于微服务比较多的(主流程涉及8+微服务)系统,如果没有服务的全链路调用跟踪那么排查故障以及性能问题就会很困难了。一般完善的全链路监控体系不仅仅覆盖微服务,而且功能也会更丰富,实现下面的功能:
-
以Log、Agent、Proxy或整合进框架的方式实现,尽可能少的侵入的情况下实现数据的收集。而且确保数据的收集不会影响到主业务,收集服务端宕机的情况下业务不影响。
-
调用跟踪。涉及到服务调用、缓存调用、数据库调用,MQ调用,不仅仅可以以树的形式呈现每次调用的类型、耗时、结果,还可以呈现完整的根,也就是对于网站请求呈现出请求的完整信息,对于Job任务呈现出Job的信息。
-
JVM的信息(比如对于Java)。呈现每一个进程JVM层次的GC、Threads、Memory、CPU的使用情况。可以进行远程Stack的查看和Heap的快照(没有进程的内存信息,很多时候基于服务器层面粗粒度的资源使用情况的监控,基本不可能分析出根本原因),并且可以设定策略进行定期的快照。虚拟机的信息查看和调用跟踪甚至可以通过快照进行关联,在出现问题的时候能够了解当时虚拟机的状态对于排查问题是非常有好处的。
-
依赖关系一览。有的时候我们做架构方案,第一步就是梳理模块和服务之间的依赖关系,只有这样我们才能确定影响范围重构范围,对于微服务做的比较复杂的项目来说,每个人可能只是关注自己服务的上下游,对于上游的上游和下游的下游完全不清楚,导致公司也没有人可以说的清楚架构的全貌。这个时候我们有全链路跟踪系统的话,可以对通过分析过去的调用来绘制出一张依赖关系的架构图。这个图如果对QPS做一些热点的话,还可以帮助我们做一些运维层面的容量规划。
-
高级分析建议。比如在全链路压测后定位分析瓶颈所在。定时分析所有组件的执行性能,得出性能衰退的趋势,提早进行问题预警。分析JVM的线程和GC情况,辅助定位High CPU和Memory Leak的问题。退一万步说,即使没有这样的自动化的高级分析,有了调用跟踪的图和组件依赖关系图,至少在出问题的时候我们人能分析出来咋回事。
-
Dashboard。非必须,只要数据收集足够全面,如之前文章所示,我们可以用Grafana来进行各种个性化的图表配置。
(4)熔断限流
比如客户端权限控制,黑白名单,限流,超时熔断,和调用链搭配起来的调用跟踪,全量操作的审计搜索,数据迁移辅助等等。常见的熔断限流有阿里开源的Sentinel。
(5)分布式事务
代理实现了分布式事务的功能(XA)。还可以实现代理层面的分布式悲观锁的功能。比如阿里来源的分布式事务中间件Seata。
(6)数据访问中间件
数据访问中间件是独立部署的数据库的透明代理,本身需要是以集群方式支持高可用,背后还需要对接多套数据库作为一个集群。常见的数据库中间件包括:ShardingSphere和MyCat。
一般而言会提供如下的功能:
-
读写分离:包括负载均衡和故障转移的功能,自动在多个从库做负载均衡,通过可用性探测,在主库出现故障的时候配合数据库的高可用和复制做主库的切换。
-
分库分表:随着数据量的增多需要分片功能。分片也就是Sharding,把数据按照一定的维度均匀分散到不同的表,然后把表分布在多个物理数据库中,实现压力的分散。这里写入的Sharding一般而言没有太多的差异,但是读取方面因为涉及到归并汇总的过程,如果要实现复杂功能的话还是比较麻烦的。由于分片的维度往往可能有多个,这方面可以采用多写多个维度的底层表来实现也可以采用维度索引表方式来实现。
-
SQL优化:随时进行SQL的Profiler,然后达到一定阈值后提供索引优化建议。类似https://github.com/Meituan-Dianping/SQLAdvisor。
(7)分布式缓存中间件
类似于数据库的Proxy,这里是以缓存服务作为后端,提供一些集群化的功能。比如以Redis为后端的开源的实现有https://github.com/CodisLabs/codis以及饿了么的https://github.com/eleme/corvus 等等。其实不采用Proxy方式做,开发一个缓存客户端在框架层面做也是完全可以的,但是之这两种方式各有优劣。代理方式的话更透明,如果有Java、Python、Go都需要链接Redis,我们无需开发多套客户端了。一般实现下面的功能:
-
分布式。这是最基本的,通过各种算法把Key分散到各个节点,提供一定的容量规划和容量报警功能。
-
高可用。配合Redis的一些高可用方案实现一定程度的高可用。
-
运维方面的功能。比如客户端权限控制,黑白名单,限流,超时熔断,全量操作的审计搜索,数据迁移辅助等等。
-
跟踪和问题分析。配合全链路监控实现一体化的缓存访问跟踪。以及更智能的分析使用的情况,结合缓存的命中率,Value的大小,压力平衡性提供一些优化建议和报警,尽早发现问题,缓存的崩盘往往是有前兆的。
-
完善的管理后台,可以一览集群的用量、性能,以及做容量规划和迁移方案。
如果Redis集群特别大的话的确是有一套的自己的Proxy体系会更方便,小型项目一般用不到。
(8)分布式定时任务
分布式定时任务的方案,都是基于单点+集群的模式,即选中一个系统作为单点保证任务不会重复,其他服务执行任务确保系统高可用、低负载。常见的比如XXL-JOB和POWER-JOB
(9)消息队列中间件
消息中间件是在分布式系统中完成消息的发送和接收的基础软件。
消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。
消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。
参考链接:
系统架构设计笔记(77)—— 中间件技术 - 掘金
互联网架构:常用基础中间件介绍_基础架构中间件-CSDN博客
一文读懂中间件-腾讯云开发者社区-腾讯云