☁️ 第二章 构建系统优先考虑云服务的时代
📄 一句话概括

云原生不是【用了容器就算】,而是四件事一起做到:容器化、微服务、声明式、不可变;前三件讲怎么拆,第四件讲怎么改——只有四件齐了,云上那套【随时扩、随时换】的机制才真正用得上。

📝 本节和前面几节的关系

上一节(优先考虑云服务的时代)讲的是为什么默认要按云做方案。这一节开始讲怎么做——默认上云之后,系统本身该怎么写才配得上云。

这两个词前面都出现过,但只出现了一角:容器在 云计算的服务器是虚拟服务器 里作为"和虚拟机并存的技术"被提过一句,微服务在 云计算对系统架构的改变 里作为架构四阶段的第三段出现过。这一节把它们拆开讲透——因为【云原生】这个词被误用得最厉害,不拆开就永远分不清哪些是真改造、哪些只是换了个包装。

一、最容易用错的地方

如果你在招聘网站上搜【云原生工程师】,会发现要求五花八门,但出现频率最高的东西就两样:容器和Kubernetes。于是很多人得出一个结论:把应用打包成容器、用上 Kubernetes,就是云原生了。

这个结论错了一半。 错的那一半很重要,因为照这个理解去改造,通常拿不到想要的结果——系统是装进容器了,可上线还是整站一起发、扩容还是要人盯着,那套【随时扩、随时换】的好处一样也没落着。

先看容器到底改了什么。

二、容器与虚拟机:隔的层次不一样

两者都提供"隔离",但隔的方式完全不同:

这个"快"不是体验上的小差别,而是能力上的分水岭。因为只有当"起一个实例"的成本低到秒级时,"不够就多起几个、不用了就关掉"才会成为常规操作。VM 时代也能扩,但扩一台要几分钟,所以大家宁可多买几台闲在那里——那又回到了第一章讲的【为峰值付钱】。

三、单体与微服务:改一处不再动全身

隔离方式决定了运行单位,而运行单位又决定了系统的切分方式:

关键不是"拆得越小越好",而是故障和变更的传播范围变小了。单体里一处内存泄漏能拖垮全站;微服务里一个服务崩了,其他功能照常。这条性质,才让云上"自动替换掉坏实例"这个动作有意义——如果每次替换都要动全站,自动化也救不了你。

四、四件事凑齐,才叫云原生

把上面两条和另外两条放在一起,才是完整的图景:

要素 它解决的问题 少了它会怎样
① 容器化 应用到哪都跑得一样 环境靠手配,换台机器就出问题
② 微服务 变更与故障的传播范围 改一处要停全站,自动化无从下手
③ 声明式 你写目标,系统去对齐 扩容靠人手敲命令,出错就停在那
④ 不可变 要改就换新的,不改在跑的 机器状态越跑越乱,坏了救不回来

①②讲【怎么拆】,③④讲【怎么改】。 前两件决定了系统的形状,后两件决定了运维的方式。只做前两件,你会得到"装在容器里的一坨"——形式上现代化了,运维照旧。

五、动手 Demo:两张对比表

下面这个 Demo 把两条主线各做一张对照表。第一张是容器与虚拟机的差别,第二张是单体与微服务的差别。

# 同样是【隔离】,隔的层次不同,能做的事就不同
vm  = {"启动": "分钟级", "镜像": "数 GB",  "一台物理机可装": "十几个"}
box = {"启动": "秒级",   "镜像": "数十 MB", "一台物理机可装": "上百个"}

# 部署单元的数量,决定了【一次变更影响多大】
monolith = {"部署单元": 1,  "故障影响": "全站"}
micro    = {"部署单元": 12, "故障影响": "一个功能"}

实跑输出:

==================================================================================================
D2 云原生的真正含义:容器与微服务到底改了什么
==================================================================================================
  【一】容器与虚拟机:都叫【隔离】,但隔的层次不一样

  对比项                  虚拟机(VM)              容器
  ----------------------------------------------------------------------------------
  启动时间                分钟级(30 秒~2 分钟)    毫秒~秒级(小于 1 秒)
  镜像体积                数 GB(含整个系统)       数 MB~数百 MB
  隔离级别                硬件级(各自内核)        进程级(共享内核)
  一台物理机上能装        十几个                    上百个
  适合的负载              长期稳定、隔离要求高      弹性伸缩、高频发布
  扩容方式                克隆整机(分钟级)        多起几个副本(秒级)

  【二】单体与微服务:拆开之后,改一处不再动全身

  维度                    单体应用                  微服务(拆成 12 个)
  ----------------------------------------------------------------------------------
  部署单元                1 个                      12 个(各自独立发布)
  一次发布影响面          整站要一起重启            只影响改动的那个
  单次启动时间            90 秒                     8 秒
  故障爆炸半径            一处出错全站不可用        只坏掉一个功能
  团队协作方式            共用一个代码仓库          按服务划分边界
  技术栈自由度            全站统一                  每个服务可各选

  【三】云原生不是【用了容器就算】,它是四件事叠起来:
     ① 容器化——把应用和它的依赖打成一个包,到哪都跑得一样
     ② 微服务——把一个大的拆成几个小的,各自能独立替换
     ③ 声明式——你写【我要 3 个副本】,系统自己去把状态调过去
     ④ 不可变——要改就换一个新的,不去改正在跑的那个
  ④ 前三件讲【怎么拆】,第四件讲【怎么改】。四件齐了,
     云上那套【随时扩、随时换】的机制才真正用得上——
     只把应用塞进容器、却还整站一起发布,那不叫云原生。

读这个输出:第一张表里最该记住的不是"容器更快",而是"快"落到了哪个具体数字上——从分钟级到秒级,跨过了三次方。第二张表里最该琢磨的是最后两行:团队协作方式和技术栈自由度。它们说明微服务不只是技术选择,它还是组织选择——你没法让两个团队维护同一个部署单元,所以服务的边界往往就是团队的边界。

六、⚠️ 2026 现状

教材 2022 年出版,这几年变化集中在容器与虚拟机的分工上:

30 秒实验

打开一个你常用的网页应用(比如在线文档或邮箱),做两个观察:

  1. 它有没有在你不知情的时候更新过? 如果有过"刷新一下界面就变了"的经历,说明它大概率是分服务发布的——这次发布没有让全站停摆,这就是微服务带来的直接体感。
  2. 你刷新页面时,有没有偶尔出现某一个区块转圈、别的区块正常? 这说明各区块是由不同服务提供的,一个慢不会拖住全部——这就是"故障爆炸半径"变小后的样子。

反过来想:如果你所在的系统每次发版都要整个停掉、还要挑半夜做,那它大概还是单体。

常见误区

  1. 错误:把应用装进容器就是云原生了。——纠正:容器只是四件事里的第一件。判断有没有真的做到,看一个场景就够了:业务量涨了三倍,你是点一下让系统自己多起几个实例,还是打电话叫人加班扩容? 如果是后者,那容器对你来说只是换了个打包格式,云的弹性并没有用上。

  2. 错误:微服务拆得越细越好。——纠正:拆分的依据是业务边界,不是数量指标。拆得过细会带来新问题:服务之间的调用变成网络调用(更慢、更容易失败)、一次业务操作要跨好几个服务(排查困难)、部署单元多了运维复杂度上升。目标是"能独立变更",不是"数量多"——一个拆成 12 个但每次仍然要一起发布的系统,还不如一个单体。

  3. 错误:虚拟机过时了,应该全部换成容器。——纠正:两者是分工,不是替代。虚拟机提供的是硬件级的隔离和长期稳定的运行环境,容器提供的是轻量与快速伸缩。今天的常见做法恰恰是两者叠加:底层用虚拟机做资源池和强隔离,上层用容器跑应用。需要强隔离的负载(多租户、合规敏感)继续用虚拟机,是很正常的选择。

  4. 错误:不可变基础设施是运维偏好,跟开发没关系。——纠正:它对开发方式有直接约束——因为"要改就换一个新的",所以应用不能把状态存在自己这台机器上。这就是为什么云原生应用要尽量做成【无状态】:状态放到外面的数据库或缓存里,机器本身随时可丢。第一章 1-15 讲故障恢复时那句"4 分钟只是机器层面",前提就是这个。

自测三问(点开对答案) 1. 为什么说容器"快"这件事,是能力上的分水岭,而不只是体验上的改善? —— 因为**它改变了"扩容"这个动作的性价比**。VM 时代扩一台要几分钟,所以常规做法是多买几台空闲机顶着峰值,本质仍是第一章说的【为峰值付钱】;容器能在秒级起实例,**"按当下需要起、不需要就关"才第一次变得现实**。云服务特点里那条【扩展性】,真正兑现靠的就是这个速度。 2. 微服务带来的最大好处,是"每个服务可以换不同语言"吗? —— **不是,那是副作用**。最大的好处是**变更与故障的传播范围变小**:改一个功能只重启一个服务,坏一个服务只影响一个功能。技术栈自由是顺带得到的——它能成立,前提也是服务之间已经解耦到"互不依赖对方怎么实现"。**把副作用当主因,容易拆出形式上分开了、实际上还绑在一起的系统。** 3. 为什么"不可变基础设施"这条会反过来要求应用做成无状态? —— 因为**如果机器随时可能被换掉,那么存在机器上的东西就随时可能消失**。所以应用必须把状态挪到外面(数据库、缓存、对象存储),本机只保留可以随时重建的运行环境。**这不是云原生的额外要求,而是"随时换机器"这个能力的必然前提**——你想享受快速替换,就得先让替换这件事变得无害。

相关笔记