互联网架构演进:从一台服务器到云原生

把互联网架构的发展史当成一个故事来听,你会发现这些"高频名词"都不是凭空冒出来的。它们是一群工程师在面对越来越大的流量、越来越复杂的业务时,一步步被逼着想出来的解决方案。

第一章:故事的起点——单机架构

一切从最简单的场景开始:你刚做了一个小网站,用户没几个,访问量极低,一天访问量可能还没你自己测试的次数多(就像写的博客一样)。这时候怎么简单怎么来,一台服务器搞定一切:

  • 应用进程跑在上面
  • 数据库也装在上面
  • 用 LAMP(Linux + Apache + MySQL + PHP)或类似开源技术栈,几天就能上线

image

这就是单机架构。就像开了个路边摊,一个人又做饭又收钱又端盘子,客人少的时候完全够用。
优点是简单、成本低、易维护;
缺点也很明显:一旦流量上来,就顶不住了。


第二章:第一次拆分——应用与数据库分离

生意有了起色,客人越来越多。你发现一个问题:厨师和收银员挤在同一个小窗口,互相卡位

业务慢慢有了起色,用户多了起来。这时候问题出现了:应用进程和数据库抢资源。应用处理请求需要 CPU,数据库做 IO 操作也需要 CPU 和内存,两者挤在一台机器上互相影响,性能直线下降。

解法:把它们拆开

image

  • 应用服务器专门处理业务逻辑和 HTTP 请求
  • 数据库服务器专门负责数据存储和 IO 操作

两者各司其职,性能明显提升。这是架构演进中的第一次分离,也奠定了后续所有拆分思路的基础。


第三章:面对高并发——集群 + 负载均衡

饭菜太好吃了,一个收银窗口排了 500 人的队

好景不长,用户又暴涨了。这次的问题更直接:单台应用服务器处理不过来

一台服务器哪怕配置拉满,也有上限,比如每秒只能处理 100 个请求。来了 500 个请求怎么办?

答案简单粗暴:500 ÷ 100 = 5,来 5 台服务器

image

这里引出了几个关键概念:

概念 说明 大白话
集群 多台服务器部署相同代码,协同处理请求 多台服务器跑一模一样的代码,一起干活
负载均衡 将流量均匀分发到各台服务器,常见算法有轮询、加权轮询、最少连接等 一个"调度员",把请求均匀分给各个服务器,别让某台累死、某台闲
水平扩展(Scale Out) 扛不住就加机器,理论上可以无限扩容 扛不住?加机器!理论上想加多少加多少
高可用(HA) 一台挂了,负载均衡自动屏蔽流量,其他服务器顶上,系统不会崩 一台挂了?调度员自动把流量切到别的机器,用户完全无感

这套组合拳是互联网系统抗高并发的基石,至今仍是最核心的手段之一。


第四章:数据库成为瓶颈——三层缓存体系

应用层扛住了,新问题出现了:大量请求穿透到数据库,数据库成了新的瓶颈

要理解为什么,先看数据库查询的原理:

应用发查询请求
    ↓
数据库先去【内存缓冲区】找
    ├── 找到了 → 直接返回(快)
    └── 没找到 → 去磁盘查找 → 加载到内存缓冲区 → 返回(慢)

内存比磁盘快 1000 倍以上,但数据库自带的内存缓冲区太小,就像你手机的运行内存——存不下所有东西。

解决思路:把"缓冲区"单独拿出来,做大做强再创辉煌?

三层缓存架构

image

打个比方:你要查一本书的某个知识点。

  • 第一层:先看自己的笔记(浏览器缓存)
  • 第二层:问同事借笔记(本地缓存)
  • 第三层:去公司图书馆找(Redis)
  • 最后:实在找不到才跑去国家图书馆(数据库)

绝大多数请求在缓存层就被拦住了,根本到不了数据库。 数据库压力从 100% 直接降到可能只剩 5%

  • 查询速度从毫秒级降到微秒级
  • 数据库压力暴跌
  • 就算数据库临时挂了,缓存还能顶一阵子,可用性也提升了

注意区分:数据库自带的缓冲区只存原始表数据。而三层缓存什么都能存——页面 HTML、接口结果、静态资源、计算结果,什么快就缓存什么

当然,缓存的引入也带来了新的问题,常见的坑有:

  • 缓存穿透:大量请求查不存在的数据,每次都打穿到数据库
  • 缓存雪崩:大量缓存同时过期,数据库瞬间被洪峰冲垮
  • 缓存击穿:某个超热 key 突然过期,瞬间所有请求直奔数据库

解法分别是布隆过滤器、随机过期时间、互斥锁。这是后端工程师的必修课,此处不展开。


第五章:读写分离——解决数据库读写阻塞

缓存解决了热点读,但写请求和非热点读仍然要打数据库

数据库有个特性:写比读慢得多。写操作会锁行、锁表,并发一高就排队,这就产生了读写互相阻塞的问题。好比一条路又跑卡车(写)又跑小轿车(读),卡车一停下来,后面全堵住。

解法:让主库专门负责写,从库专门负责读,通过数据同步保证主从数据一致。修两条路,各走各的。
image

互联网应用天生读多写少(通常读占 80%~90%),所以可以"一主多从"——一个主库负责写,多个从库负责读,压力瞬间分摊。

这就是读写分离。读写各行其道,再也不互相堵了。


系统跑了几年,数据量越来越大。订单表几亿行,日志表几十亿行,单库单表撑不住了

这时候必须对数据库进行拆分,有两个维度:

垂直分库(按业务拆)

原来:一个大数据库(用户 + 商品 + 订单 + 日志...)

拆分后:
  用户库 (user_db)
  商品库 (product_db)  
  订单库 (order_db)

不同业务互不干扰,也方便不同团队独立维护。公司大了要分部门,各管各的,互不干扰

水平分表(按数据量拆)

原来:一张 orders 表,10 亿行数据

拆分后(按 user_id 哈希取模):
  orders_0
  orders_1
  orders_2
  ...
  orders_N

数据分散到多张表,每张表数据量可控。配合数据库中间件(如 ShardingSphere、MyCat),对应用透明,不需要改大量业务代码。

至此,数据库从单点变成了分布式数据库,存储和并发能力可以无限水平扩展。
image


第六章:CDN + 反向代理——解决访问速度与安全

用户遍布全国,有人秒开页面,有人转圈转半天。为什么?因为数据要从中心机房跑到用户手机上,距离越远越慢

另外一个问题:应用服务器直接暴露在公网,就像把家门钥匙挂门外,风险太大。

两个经典组件来救场:

CDN(内容分发网络)

在全国各地铺设节点,把静态资源(图片、JS、CSS、视频等)提前缓存到离用户最近的节点。
用户不用每次都跑到中心机房取数据,就近取,速度直接起飞。

反向代理

放在用户和应用服务器之间,公网请求先到反向代理,再转发到内网应用服务器。(用户和应用服务器之间的"门卫":)
image

好处:

  • 隐藏真实 IP:黑客打不到你真正的服务器
  • 流量清洗:过滤恶意请求、DDoS 攻击
  • SSL 卸载:HTTPS 加解密交给它干,应用服务器轻装上阵
  • 顺手还能做负载均衡

第七章:搜索引擎 + NoSQL——应对复杂查询

传统关系型数据库(MySQL)是万能选手,但遇到某些场景就力不从心了:

  • 电商搜商品:SELECT * FROM products WHERE name LIKE '%手机%'——百万数据,慢到起飞
  • 社交找好友的好友的好友——多层关系查询,SQL 写到崩溃
  • 日志分析:几十亿条数据做聚合统计——MySQL 直接投降

术业有专攻,让专业的工具干专业的事。

搜索引擎(Elasticsearch / Solr)

利用倒排索引实现全文检索秒级响应。普通数据库是"给我一个 ID,我返回内容"。倒排索引反过来——"给我一个关键词,我告诉你哪些文档包含它"
天然为搜索而生

用户搜索"苹果手机" → Elasticsearch 倒排索引 → 毫秒级返回结果

倒排索引原理:不是从文档找词,而是从词找文档,天然适合搜索场景。

NoSQL 数据库

针对非结构化、半结构化数据,以及高并发、易扩展的场景:

类型 代表产品 适合场景
KV 存储 Redis 缓存、计数器、分布式锁
文档数据库 MongoDB 灵活 Schema、JSON 文档存储
列式数据库 HBase, Cassandra 海量数据写入、时序数据
图数据库 Neo4j 社交关系、知识图谱

关系型数据库 + 搜索引擎 + NoSQL,三者协同,让系统具备了应对复杂场景的能力。


第八章:从单体到分布式——解决业务膨胀

随着业务增长,最初一个"什么都有"的应用长成了巨石应用(Monolith),问题接踵而来:

  • 改一行用户代码 → 整个应用重新部署(发布风险大)
  • 多人同时改代码 → 天天冲突(协作效率低)
  • 订单模块压力大想加机器 → 只能把整个应用一起扩(资源浪费)

打个比方:相当于一家公司所有部门挤在同一间办公室,市场部打电话吵到技术部写代码,行政部搬桌子挡了财务部的路。

解法:按业务边界拆分

	    原来的巨石应用
    		 ↓ 拆分
用户系统 | 商品系统 | 订单系统 | 支付系统

每个系统单独部署、单独发布、单独扩容,互不影响,这就是分布式架构

但拆完新问题来了:系统之间如何通信?

RPC(远程过程调用)

让跨机器的服务调用像调用本地代码一样简单丝滑。常见框架:Dubbo、gRPC、Thrift。

// 虽然 userService 跑在另一台机器上,但写起来和本地方法没区别
UserInfo user = userService.getUserById(userId);

服务注册与发现

服务越来越多,如何快速找到目标服务的地址?
注册中心(Zookeeper / Nacos / Consul):

  • 服务启动 → 自动注册:"我是用户服务,地址是 192.168.1.10:8080"
  • 调用方 → 查注册中心 → 拿到地址 → 直接调用
  • 服务挂了 → 注册中心自动摘除,不会把请求发到"死服务"上

注册中心还负责健康检查,服务挂了自动摘除,恢复后自动注册。
image

消息队列

服务之间相互调用、相互等待,一个服务卡住,整条链路都跟着堵死,就像多米诺骨牌一样雪崩。

消息队列(Kafka / RabbitMQ / RocketMQ)的核心价值:

服务 A:我把消息丢进信箱,就走了,不等回复
服务 B:我按自己的节奏来取信、处理

image

三大价值:

  • 异步解耦:服务之间不再相互等待
  • 削峰填谷:流量突增时先把请求存起来,按系统能力慢慢消化
  • 可靠传递:就算服务临时挂了,消息不丢,恢复后再处理

第九章:微服务架构——极致的弹性与灵活性,拆到极致

分布式架构用了几年,发现拆的还不够细。就拿用户系统来说,里面塞了登录、个人信息、会员、地址管理……还是一大桶。会员模块流量暴涨想扩容?抱歉,只能连带整个用户系统一起加机器。

于是,进一步拆分:一个服务只干一件事

用户系统 → 拆成:登录服务 / 个人信息服务 / 会员服务 / 地址服务

image

这就是微服务架构——分布式的升级版,拆得更细、更灵活。

微服务的核心优势

维度 效果
独立部署 某个服务出 bug,只影响这一个功能,不会拖垮整个系统
独立扩容 大促时只给订单、支付加机器,其他服务不动,省钱
技术自由 各团队自选技术栈,Go、Java、Python 各玩各的
团队解耦 几十个团队各管各的服务,互不打扰

微服务配套体系

服务数量从几个变成几十上百个,没有配套体系会乱成一锅粥::

  • API 网关:统一入口,做鉴权、限流、路由
  • 全链路追踪(Zipkin / SkyWalking / Jaeger)::一个请求经过了哪些服务、每一步花了多久,一目了然
  • 限流熔断降级(Sentinel / Hystrix / Resilience4j):流量太猛时自动"保险丝跳闸",保护系统不崩
  • 配置中心(Nacos / Apollo):几百个服务的配置统一管理,改一处全生效
  • 服务治理:统一监控、日志聚合、配置中心(Apollo / Nacos)
  • Service Mesh(服务网格)(Istio):把服务治理的逻辑从业务代码中抽出来,放到 Sidecar 代理中

把这些都配齐,就是大厂标准的微服务体系,扛住千万级、亿级流量都不在话下。


第十章:容器化——终结"我电脑能跑

服务从原来几个变成几百个,每个服务上线都要:配环境 → 装依赖 → 调参数……稍有不同就出现"我电脑能跑,服务器跑不起来"的玄学 bug。
image

解法:把服务和它需要的运行环境一起打包成一个密封盒子

这就是 Docker 容器

# 示例:把一个 Java 微服务打包成镜像
FROM openjdk:17-jre-slim
COPY target/user-service.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

一次构建,到处运行。彻底解决环境不一致的世纪难题。
image

Docker 的核心概念

  • 镜像(Image):只读的打包文件,包含代码 + 依赖 + 环境
  • 容器(Container):镜像运行后的实例,像一个轻量级虚拟机
  • 仓库(Registry):存放镜像的地方,如 Docker Hub、Harbor

第十一章:Kubernetes——容器的"大管家"

Docker 解决了"打包"问题,但新问题来了:几百上千个容器,谁来安排它们跑在哪台机器上?谁来管它们的死活?

靠人管?不现实。

Kubernetes(K8s) 登场——容器编排的王者。

K8s 能做什么?

流量高了 → 自动多启几个容器分担压力(HPA 水平自动扩缩容)
流量低了 → 自动关掉多余容器省钱
容器挂了 → 自动重启,甚至换台机器重新跑
发新版本 → 逐步替换旧容器,用户完全无感知
资源调度 → 自动决定每个容器跑在哪台机器上最合适

全程不用你管,运维从"救火队员"变成了喝着咖啡看仪表盘"基础设施工程师"。

K8s 核心概念速览

概念 说明
Pod K8s 最小调度单元,一个或多个容器的组合
Deployment 管理 Pod 的副本数、滚动更新
Service 为 Pod 提供稳定的访问入口,外面好找到它
Ingress 处理外部流量进入集群的路由。管理从外面进来的流量怎么分配
Namespace 逻辑隔离,给不同环境(开发/测试/生产)划地盘,互不干扰

第十二章:云原生——架构的终极形态(目前)

就算有了 K8s,还是得自己买服务器、维护机房。为了应对流量高峰(比如双 11),你得提前备好大量服务器。但平时流量没那么大,这些机器就闲着吃灰——钱花了,资源浪费了

最终解法:别买服务器了,直接租"云"

云平台(AWS、阿里云、腾讯云)就像一个无限大的资源超市

  • 要 CPU?拿
  • 要内存?拿
  • 要带宽?拿
  • 用完还回去,按秒付费

底层机房?不用关心。硬件故障?平台帮你搞定。你只管写业务代码。

image

云原生(Cloud Native) 是一套充分利用云平台弹性的架构理念和技术体系,核心特征:

  • 容器化:所有服务跑在容器里
  • 微服务:服务粒度细,独立部署
  • DevOps & CI/CD:代码提交自动测试、构建、部署
  • 弹性伸缩:根据流量自动扩缩容,分钟级响应
  • 可观测性:日志、指标(Metrics)、追踪(Tracing)三位一体

总结:架构演进全景图

阶段 解决的问题 核心技术 大白话
单机架构 从零开始,快速上线 LAMP/单节点 一台机器搞定
应用与数据库分离 资源争抢 两台独立服务器 分两台机器
集群 + 负载均衡 高并发、高可用 Nginx/LVS、水平扩展 加机器 + 调度员
三层缓存 查询性能、数据库压力 Redis、CDN、本地缓存 把热数据放内存
读写分离 数据库读写阻塞 MySQL 主从复制 主库写、从库读
分库分表 海量数据存储 ShardingSphere、MyCat 把数据拆开存
CDN + 反向代理 访问速度、系统安全 Nginx、Cloudflare 就近取 + 藏起来
搜索引擎 + NoSQL 复杂查询 Elasticsearch、MongoDB、Redis 专业的事交给专业工具
分布式架构 业务膨胀、代码维护 RPC、服务注册发现、消息队列 按业务拆成独立系统
微服务架构 团队协作、极致弹性 Spring Cloud、Dubbo、Kafka 拆到极致,一个服务一件事
容器化 环境一致性、运维效率 Docker Docker 打包一切
Kubernetes 容器编排、自动化运维 K8s、Helm 自动编排调度
云原生 成本、弹性、自动化 AWS/阿里云、Serverless、Istio 上云,按需付费

架构师的三个内核思维

学完这段旅程,送给大家三条元认知:

1. 没有最好的架构,只有最适合的架构

业务推着架构走,架构服务于业务。 过度设计是大忌。

2. 架构演进的本质:用复杂度换性能

加机器、加组件、加分层,本质上都是用更高的复杂度换取更强的性能和可用性。天下没有免费的午餐,每次升级都有代价。关键是:**值不值得换?

3. 万变不离其宗——五大目标

无论架构怎么变,评判标准始终是这五个:

  • 高性能:用户感觉"快"
  • 高可用:系统不轻易"崩"
  • 可伸缩:流量来了能扩,退了能缩
  • 可扩展:新业务能快速接入
  • 够安全:数据不泄漏,不被攻击

写在最后

从一台小服务器,到如今弹性、自动化、高可用、可无限扩展的云原生架构,每一步都有迹可循,每一步都在解决真实的问题。

架构不是一蹴而就的,是被业务一刀一刀雕刻出来的。

理解了这条演进之路,再去看那些眼花缭乱的技术名词,你会发现——它们都只是在对应阶段解决特定问题的工具。工具会过时,但解决问题的思维方式,是永远不过时的。


参考资料:

posted @ 2026-06-09 10:42  江鸟Dev  阅读(9)  评论(0)    收藏  举报