前言
博主最近在学中间件,理解互联网应用架构的演进过程,对于理解中间件在整体结构中的定位是十分重要的
常见概念
应用(Application)/系统(System)
完成某种服务的一个/一组程序
模块(Module)/组件(Component)
系统中,一个独立的功能称之为一个组件
分布式(Distributed)
系统中的模块被部署到多个服务器上,这些模块协同完成一系列工作,这样的系统叫分布式系统
集群(Cluster)
系统中的模块被部署到多个服务器上,完成特定目标的一个/多个模块被称为集群
主(Master)/从(Slave)
集群中,承担更多职责的程序被称为主,承担附属职责的程序被称为从。主节点需要向从节点同步数据
中间件(Middleware)
和业务无关的服务,功能更加通用。1. 数据库 2. 缓存 3. 消息队列
八大架构演进过程
单机架构
将所有服务(应用服务+数据服务)部署在同一台服务器上
用户访问应用服务,应用服务根据用户需求访问数据库服务,并将得到的数据返回给用户
由于互联网早期,应用/web访问量小,所以单机足以满足需求
优点:
- 部署简单
- 成本低
缺点: - 存在性能瓶颈,用户无限增长但资源有限
- 数据库和应用竞争资源
应用数据分离架构
由于单机架构的性能缺陷,当用户量增多时,网站的响应速度变慢
此时演变出了应用数据分离架构:将应用服务和数据服务部署在不同服务器上
应用服务和数据服务间的交互通过网络完成
(具体来说:使用cpp-httplib/Spring编写应用程序,应用服务接收用户请求并将其转换成数据库语句,接着将语句通过数据库客户端与网络发送给数据库服务端,服务端完成数据操作)
对于应用服务器:可以适当增加CPU、内存资源,因为业务的逻辑将占用更多的CPU和内存
而对于存储服务器:可以适当增加磁盘资源,甚至使用SSD固态硬盘,提高数据的读写速度
优点:
- 性能相比单机架构有所提升
- 数据库和应用分离,提高了容灾能力
缺点:
- 硬件成本变高
- 无法应对海量并发
应用服务集群架构
当用户的请求量增加,应用服务无法及时处理这些海量请求,导致响应时长过长,用户体验差
此时增加应用服务器数量(横向扩展),在应用服务和数据服务之间引入负载均衡(决策层),使应用服务以集群的方式运作。引入负载均衡后,每台应用服务器承担相同的压力
负载均衡器对于请求的承担能力要远大于应用服务器,因为负载均衡器只涉及到分配算法,不需要处理请求
这一架构涉及到两个软件设计哲学:
- 一个设备扛不住,就多加几个设备
- 没有什么问题是加一层无法解决的
当并发量越来越大时,Nginx扛不住了,那就多用几个Nginx
Nginx一多,无法实现Nginx之间的负载均衡,再引入决策层,使用LVS/F5实现Nginx的负载均衡
LVS/F5也扛不住了,那就多个几个LVS/F5
LVS/F5一多,无法实现负载均衡,直接修改DNS集群(添加多个IP地址),使之作为我们的负载均衡
DNS也扛不住?修改用户电脑的host文件,直接绕过DNS解析
优点:
- 应用服务高可用,不会因为一个服务器出问题,整个站点挂掉
- 服务具备高性能
- 应用服务可以横向扩展
缺点:
- 数据服务成为瓶颈
- 运维工作增多,维护成本增加
- 硬件成本高
读写/主从分离架构
y应用服务能够处理海量请求时,数据服务成为性能瓶颈
将数据服务进行读写/主从分离,主库负责写操作,从库负责读操作。主从数据库使用数据同步技术保证数据一致
为什么要读写分离?互联网应用一般读多写少,部署多个从数据库负责读操作,可以有效地提高响应速度
但是应用服务如何区分读写请求并将其发送给不同的数据库?因此在应用服务和数据服务之间引入一层中间层,该中间层能够识别读写流量被分流(负载均衡)给响应的数据服务。该中间层对应的软件:MyCat,TDDL
优点:
- 读写分离后,数据服务的读写能力都得到提升
- 数据库拥有从库(备份),可用性(容灾能力)提升
缺点:
- 同步服务延迟高或者挂掉时,导致读库和写库数据不一致
- 成本进一步地增加
- 热点数据的频繁读取导致数据库的负载率很高
冷热分离架构
互联网应用中,20%的数据就能应对80%的请求,这些数据被称为热点数据
对于热点数据,如果能做到更快的读写,那么响应时长将大大减少
所以引入缓存库,将热度高的数据放入缓存库中,由应用服务判断数据是否为热点数据(是否需要访问主从数据库)
缓存库的代表为redis
优点:
- 大幅降低数据库的访问请求,性能提高明显
缺点:
- 带来了缓存一致性,缓存击穿,缓存失败,缓存雪崩等问题
- 成本进一步增加
- 数据不断增多时,单个数据库的大小太大,查询速度降低,导致数据库再次成为性能瓶颈
垂直分库架构
冷热分离架构主要是为了应对更高的请求量,但数据服务器的容量有限,当数据量越来越大时,存储是一个问题,如何高效地查询也是一个问题
若库太大:将数据库进行拆分,每个数据服务器存储一个/一部分的数据库(分库)
若表太大:将表进行水平拆分(分表),将不同表的列属性进行拆分,根据类型,属性将字段存储到不同的数据集群中,每个数据集群都有一个主库与多个从库,查询时不会干涉其他从库。使用MyCat/TDDL中间件能够自动分库/分表
如电商网站将用户消息,订单消息,产品消息分割成不同的数据库,每个数据库包含特定类型的数据
典型分布式数据库:Greenplum、TiDB、Postgresql XC、HAWQ 等
优点:
- 提高了数据吞吐量,数据服务不再是瓶颈
缺点: - 处理事务的难度增加
- 数据服务和应用服务耦合,应用服务的修改将导致整体服务的重新部署
微服务架构
之前的所有架构,一个应用服务器负责很多业务,这将导致一台服务器的代码变得复杂,同时耦合性增加。为了方便代码的维护,需要将负责复杂业务的服务器进行拆分,拆分成功能单一的更小的服务器(微服务)。同时将开发人员进行分组,以更好地开发与维护服务
微服务是一种架构风格,按照业务模块来划分代码使得每个模块的职责更加清晰,相互之间的迭代升级能够做到独立
之前的架构存在的问题:
- 扩展性差:修改一点程序就需要重新构建代码
- 持续开发困难:重新构建代码导致无法轻松地发布版本
- 不可靠:系统中的一个功能出现bug,导致整个系统出问题
- 不灵活:无法使用不同的技术构建单体应用程序
- 代码维护难:功能耦合在一起,难以阅读
为解决以上问题,使用了微服务架构
优点:
- 灵活性高,部署时弹性大
- 独立扩展
- 提高容错性
- 容易引入新技术
- 功能复用
缺点:
- 运维复杂度高:例如环境冲突问题
- 系统的性能下降:独立出来的每个模块需要通过网络进行通信,网络的速度比磁盘还慢
- 处理故障困难:一个请求困难调用了多个微服务,出错难以定位
容器编排架构
借助容器化技术(docker)将应用/服务打包为镜像,通过容器编排工具(如k8s)来动态方法和部署镜像,服务通过容器化方式运行
出现原因:
- 微服务拆分太细,服务的部署工作量大,配置复杂容易出错
- 微服务之间的运行环境可能冲突,需要更多的资源或者修改配置来解决冲突
优点:
- 隔离性好:不会产生环境冲突
- 部署、运维简单:k8s的容器编排
- 支持滚动更新:版本间的升级与回滚通过命令即可完成
缺点: - 技术栈多,学习成本高
- 服务器成本高