Skip to content

浅谈互联网架构演变

前言


可以将某个项目或产品的架构体系按照如下方式分层:

  • 业务层面:项目业务体系
    • 技术层面:
      • 数据架构:数据持久层策略
      • 应用架构:应用层的实现方式
    • 部署架构:部署方式,自动化持续集成等策略

针对每一层也随着时间的变化而变化。


业务架构


单体模式


早期的互联网产品多为单体系统,特点是以业务为导向,往往形成业务团队各自为战,在新业务线出现时需求大量增长。

这里补充部分业务模式的概念:

  • B2B:企业与企业之间的供销模式
    • B2C:企业面向消费者的交易模式
    • C2C:消费者与消费者之间的交易模式
    • O2O:线上与线下业务混合模式

随着公司的业务发展,业务层面会不断向 B2B、B2C 等扩张。

这就引出了单体架构的局限性:

  • 功能冗余:B2B、B2C 会有相同的业务重叠,导致多个单体系统功能近似或冗余
    • 数据不互通:多个跨域业务下,对于同一用户群体的数据不能互相沟通

功能冗余会带来成本的浪费(开发运维成本),数据的不互通带来业务壁垒,跨域业务间数据难以打通。


中台战略


为了解决单体架构带来的问题,阿里在 2015 年提出了中台战略,这是一种企业架构,而不是单纯的技术层面。

这里再细化一下单体系统相较中台战略的局限性:

  • 技术和业务架构上:
    • 单体系统功能重复,而抽调出中台可以大幅减少冗余代码的开发
    • 业务集成度高,开发和运维成本高,而中台模式下,基础业务也下沉到技术部门,甚至通过技术反推业务发展
    • 对于多变的需求,中台战略可以将业务细化分层,上层业务针对产品快速迭代,下层业务持续沉淀,为上层业务封装底层接口
  • 组织架构上:
    • 单体架构下,往往是每个项目就是一个团队,团队随项目扩张不断增大或重组复用,利用率低
    • 中台模式下,可以将上层业务和下层业务的团队分离,并将各个中台单独立项,提高利用率

除此之外,中台战略在业务扩展方面具备先天性优势:

image-20231226002455240


去中台化


虽然中台战略看起来已经足够优秀,但目前又呈现出了去中台化的趋势。

在大市场不断跟风的情况下,中台战略暴露出来的问题也越来越多:

  • 中台战略需要过硬的技术支撑,大部分的公司没有完善的中台构建方案
    • 公司业务差距太大,中台复用度不高,中台带来的生产价值远远小于中台的开发和运维成本
    • 高度依赖中台的业务体系之间,耦合度严重提高

甚至中台战略的鼻祖——阿里的中台战略发展也没有达到预期,在反垄断的大背景下,减少大而集中的部门,拆分不同业务线独立发展,降低耦合。


数据架构


单体模式


早期的单体项目业务简单,一般只需要单体数据库(多为 MySQL),但随着业务体量不断增大,这一时期往往引发追逐商业大型数据库(Oracle)。

单体数据库架构多见于早期的 JavaWeb 和 SSH 项目:

  • 通过 JDBC 直连,简单直接
    • 数据库用 MySQL,或大型商业 DB
    • 单库上的机器 IO 及 CPU 性能很快达到上限

主从读写


淘宝以前就是 MySQL,后来更换为了 Oracle,直到 2007 年又从 Oracle 回迁为了 MySQL,这个历程中实现了主从库的部署与读写分离。

这一架构的特点如下:

  • 应用层连接多个数据库,数据库之间形成主从关系,主库为写,从库上读,分离读写压力
    • 数据库集群策略,一主多从或双主单写,提升数据层的容灾和高可用能力

但是这一架构也避免不了带来新的问题:

  • 数据不一致:主库到从库之间数据要进行同步,不同的数据同步策略会产生对应的问题
    • 单库瓶颈:业务越来越多,表数量越来越多,甚至可能会出现单个库几百张表的现象
    • 数据局限:依然无法解决单表大数据的问题

分库分表


为了解决单库的数据局限性问题,又引入了分库分表的解决方案:

  • 水平分库:将一个库的数据拆分到多个库中
    • 水平分表:将一张表的数据拆分到多个表中
    • 垂直分表:将一张表的多个字段拆分到多个表中。

对于垂直分库,一般是分布式架构下,按照业务将数据库进行拆分,保存不同的表和数据。

对于分库分表也会不可避免地带来新的问题:

  • 分库:不同的数据库,所以无法使用数据库事务,而分布式事务的效果并不理想,多采用幂等和最终一致性方案
    • 分表:拆了再聚合是一对矛盾,例如按下单时间维度的分表,需要按用户排序统计变得异常困难

高速缓存


数据库往往是系统的瓶颈,即便通过垂直分表可以将冷热数据进行分离,但从本质上仍然无法提升 IO 瓶颈。

因此,又提出根据数据的冷热划分,热点数据如类目、商品基础信息放在高速缓存中,再其他数据延迟加载方案:

  • redis:性能可靠,纯内存,自带分片,集群,哨兵,支持持久化,几乎成为当前的标准方案
    • memcache:性能可靠,纯内存,客户端需要自己实现,无持久化
    • ehcache:非分布式,简单,易维护,可用性一般

引入缓存,在实际生产中也会遇到问题:

  • 缓存击穿:单一 Key 失效,遇到大量请求压垮数据库
    • 缓存雪崩:大量 Key 失效,遇到大量请求压垮数据库
    • 缓存穿透:不存在的 Key,遇到大量请求压垮数据库
    • 数据不一致问题:数据库更新,缓存也要更新保持一致性

数据多样化


数据库和缓存只是一种基本的存储手段,除了这些,其他各种形式的存储结构和存储需求也相继涌现:

  • NoSQL:非关系型数据库,如:Redis,MongoDB,Neo4j
    • 分布式文件存储:存储不同文件,如:Hdfs,Fastdfs,CephFs,MinIO
    • 搜索引擎:解决海量数据搜索问题,如:Lucene,Elasticsearch

针对这些需求,带来的架构层面的挑战也是巨大的:

  • 数据可靠:面对高并发等场景,要保证数据服务的高可用
    • 数据运维:多数据服务下,对应系统的容灾措施也相应复杂,维护成本水涨船高
    • 数据安全:要求能够针对不同数据的访问权限进行隔离

应用架构


单机调优


互联网早期项目模式多为 MVC 模式:

  • Model:模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
    • View:视图代表模型包含的数据的可视化。
    • Controller:控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

这一时期的项目单机特点是:

  • 每个项目独立为一个 MVC 结构,部署在应用服务器上(Tomcat、JBoss、WebSphere、WebLogic)
    • 需求迭代快,项目体量越来越大,一个 war 包动辄几百兆
    • 技术方案不成熟,有大量历史问题遗留(屎山)

由于单机性能瓶颈问题,这一时期的项目往往都推崇 JVM 单节点调优。


动静分离


为了解决单机瓶颈,又提出了应用服务集群的动静分离方案:

  • 静态响应:Tomcat 对静态文件响应一般,提取静态文件,直接由 Nginx 响应
    • 动态代理:后端 API 通过代理转发给 Tomcat 应用机器(集群)

在这一时期的项目特点是:

  • 项目结构大幅调整,由原来的一体化 MVC 转换为后端 API + 前端形式
    • 前后端的分工变得更明确,互相并行开发,独立部署

这一时期大量的 Apache + Tomcat 已初具前后端分离架构的雏形,直到后来被 Nginx 几乎一统江山。


SOA


单纯的动静分离只解决了自身服务的项目结构,跨项目接口调用时,必须经过 REST 请求,不利于服务之间的交互。

因此又提出了面向服务的架构——SOA:

  • SOA 是一种建设企业 IT 生态系统的架构指导思想,SOA 的关注点是服务
    • 服务是最基本的业务功能单元,通过将业务系统服务化,可以将不同模块解耦
    • 各种异构系统间可以轻松实现服务调用、消息交换和资源共享

image-20201210141921958

对于 SOA 的落地目前有两种主要表现形式:

  • 分布式服务化:采用 SOA 去中心化的落地方式,典型的落地技术栈:Dubbo + Zookeeper,服务之间依靠 RPC 框架互相调用
    • 集中式管理:偏重于以 ESB 作为基础支撑技术,以整合集成为核心,将各个新旧系统的业务能力逐渐在 ESB 容器上聚合集成

这一阶段的项目特点鲜明,技术难度大:

  • 界限把控:服务的粒度、拆分和公共服务提炼需要架构师的全局把控,设计不好容易引发混乱
    • 部署升级:服务数量增多,人工部署变得不现实,必须借助自动化运维
    • 服务可用性:抽取的微服务因需要被多个上层业务共享,对系统整体的容灾能力要求提高
    • 熔断和限流:做好服务熔断和限流,提防服务单点瓶颈造成整个系统瘫痪

微服务


当分布式架构成为时代主流后,一种基于 SOA 的升级版——微服务架构也横空出世,它和分布式架构的主要区别如下:

  • 微服务架构的拆分颗粒度更细、更小,中台化得以实现
    • 服务的治理强,容易构建成熟的容灾和高可用集群体系
    • 微服务的技术栈更全、更成体系,技术栈内部的技术组件也是基于微服务的思想来做的

image-20201210142042606

同时,这种架构也有需要平衡的地方:

  • 服务拆分:拆分粒度并非越小越好,太小会带来部署、维护等一系列成本的上升。
    • 接口约束:系统增多,各个服务接口的规范化日益重要,要求有统一的服务接口规范,推动企业消息总线的建设。
    • 权限管理:服务之间的接口要做好鉴权,借助 OAuth2 等手段,实现服务之间的权限认证。

部署架构


单机部署


最早的单机项目部署方案大多为:

  • 采用 WAR 包部署与发布,数据库等资源同台机器连接,例如早期采用 Tomcat + WAR 的形式,后来则是 java -jar
    • 单机性能达到瓶颈后,只能通过提升机器配置的方式来提升性能,成本较高。

这种单机部署架构在业务发展的初始阶段尚可支撑,但随着访问量的上升,这种部署架构无法达到业务的性能要求。


角色划分


如果项目再大一些,可以把数据库、缓存、消息等中间件剥离出去,单独用机器来部署:

  • 多台机器:Tomcat 与 MySQL 各自独占机器资源。
    • 针对性扩容:Tomcat 应用机更注重 CPU 的运算和内存,MySQL 更注重 IO 与磁盘性能,针对各自情况扩容。

在这种方案下,可以将 DBA 分离出来单独维护数据库服务器,但同时也带来了数据安全方面的问题。


应用集群


应用集群部署带来的最大优势就是——负载均衡,此时期常见技术栈为:

  • Apache:早期负载均衡方案,性能一般。
    • Nginx:七层代理,性能强悍,配置简洁。
    • HAProxy:性能同样可靠,可做七层或四层代理。
    • LVS:四层代理,性能最强,Linux 集成,但配置麻烦。
    • F5:四层代理,硬件负载。

image-20201221111636625

这一方案的特点是:

  • Session 会话:集群环境下,用户登录需要分布式 Session 做支撑。
    • 分布式协同:分布式环境下对资源的加锁要超出线程锁的范畴,上升为分布式锁。
    • 调度问题:调度程序不能多台部署,容易跑重复,除非使用分布式调度,如 ElasticJob。
    • 机器状态管理:多台应用机的状态检测与替换需要做到及时性,一般 Nginx 层做故障转移。
    • 服务升级:滚动升级成为可能,灰度发布。

对于更大的部署,往往采用多层代理

  • 动静态资源均有多个 Nginx 负载,入口统一交给 LVS 负载。
    • 但是 LVS 依然是单一节点,即使 Keepalived 做到高可用,流量仍然需要在唯一入口进入。

image-20201221110843244


异地访问


为了提升系统的物理容灾能力,解决机器部署的扩容问题,又产生了多机房部署策略:

  • 将相同的系统部署多份,分散到异地多个机房,或者电信、移动等多个网络中。
    • 不同地点、不同网络接入的用户,有了不同的访问入口和选择。

此时,对于异地访问也有对应的访问策略:

  • DNS 轮询:通过 DNS 的策略轮询解析,可以实现机房层面的扩容。
    • CDN:就近原则,使用户获得就近的机房访问相关资源。

多机房部署成本较高,一般只有规模较大、具有雄厚市场支撑的公司才会使用,同等条件下远不如上云来得实惠。


云平台


近年来,针对中台化建设及微服务数量的飙升,在快速部署和资源弹性伸缩的需求下,容器化与云平台逐渐兴起。

image-20200402095344710

云平台部署下,常见的技术方案为:

  • 虚拟化:vm 方案,Openstack,Vmware,VirtualBox
    • 容器化:docker
    • 持续集成:Jenkins,CI/CD
    • 编排:swarm,k8s,k3s
    • 云化:私有云到企业云

云平台部署与传统部署方式最大的优势在于资源的灵活扩容和回收,针对活动期间弹性扩容,非活动期间回收闲置资源。

但同时云平台部署需要运维层面的高度支撑,门槛较高;其次,对应风险上,云平台瘫痪也会造成不可计量的损失,要对系统风险进行合理预估。


总结


纵观近年互联网架构的演变,不难看出,任何体系都不是一成不变的,架构体系往往随着业务需求不断革新。

因此,架构要服务于业务,而不能脱离业务存在,任何架构的设计都要贴合实际的业务场景。

技术上不断收敛,因为引入新技术必然会带来新问题,尽量追求原生,降低项目的开发和维护成本。

对于架构的扩展性要适度取舍,要考虑到互联网产品的周期,不能过分保留。