摘要:从 CGI 每次重启进程的"外包临工"模式,到 PHP 进程复用的"自家雇员"模式。第一代和第二代物流系统的关键差异在于进程是否可以复用,这是 Web API 演进史上的第一个重要转折点。
🚚 物流系统的演进史
大蟒蛇法师的困惑
🐍 大蟒蛇法师:"灵狐法师问我,FastAPI 是不是第一代物流系统?其实不是的。在 FastAPI 之前,已经有很多物流系统了。让我给你讲讲物流系统的演进史,以及不同法师们的物流系统。"
核心理解:
- FastAPI 不是第一代物流系统
- 在 FastAPI 之前,已经有很多物流系统(Flask、Django、Express 等)
- 这些物流系统都在不断演进,适应不同的需求
- REST API 是一个概念,不是某个具体的物流系统
- 不同的法师有不同的物流系统
法师角色介绍
在魔法世界里,不同的法师负责不同的后端技术:
- 🐍 大蟒蛇法师 :Python 后端,负责 Flask、Django、FastAPI 等 Python 物流系统,需要与灵狐法师合作(前后端分离)
- 🦊 灵狐法师:前端开发(JavaScript),负责卖货给客户,与大蟒蛇法师、夜狐法师合作
- 🌙 夜狐法师:Node.js 后端,隐藏于黑暗中,不露面,与兄弟灵狐法师合作,负责后端配置(前后端分离)
- 🧵 PHP 织布师 :PHP 后端,负责 PHP 物流系统,不需要与灵狐法师合作(传统全栈模式,直接返回 HTML)
- ☕ 黑水甲瓦法师 :Java 后端,负责 Servlet、Spring 等 Java 物流系统
- Servlet 时代(1990s) :主要是传统模式,Servlet + JSP,直接返回 HTML,不需要与灵狐法师合作(前后端不分离)
- 现代模式(Spring MVC,2010s+) :可以前后端分离,提供 REST API,需要与灵狐法师合作
- 🛡️ 蓝盾法师 :ASP.NET 后端,概念法师,从彩色方块世界来的,没人见过他的真身,只有外号
- 传统模式 :类似 PHP 织布师,直接返回 HTML,不需要与灵狐法师合作
- 现代模式 :ASP.NET Core Web API,需要与灵狐法师合作(前后端分离)
📜 第一代:原始物流系统(CGI、Servlet)
时代背景
🐍 大蟒蛇法师:"最早的物流系统,就像最原始的送货任务。每次订单都要重新启动整个送货任务,效率很低。那时候,CGI 和黑水甲瓦法师(Java)的 Servlet 系统就是这样的。"
CGI 是什么?
🐍 大蟒蛇法师:"CGI(Common Gateway Interface,通用网关接口)是一个接口标准,定义了 Web 服务器如何与外部程序通信。在原始时代,没有完整的备货流程,每次订单都要重新开始。"
CGI = 启动马车和道路的方法(接口标准):
- 不是完整的物流系统:而是"如何启动马车和道路"的方法(接口标准)
- 定义了接口标准:定义了 Web 服务器如何调用外部程序的接口标准
- 不是具体的物流系统:而是一个接口标准,定义了如何与外部程序通信
- 通用接口:所有法师都可以使用这个接口标准
- 每次请求都要启动新进程:每次订单都要重新启动程序进程(整个送货的任务)
- 处理完就结束:程序处理完订单后,进程(整个送货的任务)就结束了
CGI 的定位:
- CGI = 接口标准:定义了"如何启动马车和道路"的方法
- 不是完整的物流系统:只是定义了如何调用外部程序的接口
- FastAPI 比它完整得多:FastAPI 是完整的物流系统(框架),包含路由系统、中间件、数据验证等
CGI 时代 = 原始时代,没有完整的备货流程
☕ 黑水甲瓦法师:"在 CGI 时代,没有完整的备货流程。收到订单之后,我会启动整个送货任务,去到每个仓库,每个仓库的大门都需要大开,从材料的查找开始,一个个去找,然后再制作。每次来新订单,都要重新启动整个送货任务,一个个仓库去开,然后做产品。同样的流程没有被记录和筛检,所以等于每次都是新的。"
CGI 的工作方式(魔法仓库比喻):
plain
客户下单
↓
🛡️ 阿帕奇守护者(Web 服务器)收到订单
↓
☕ 黑水甲瓦法师:"启动整个送货任务!"(启动新的 CGI 程序进程)
↓
☕ 进程 = 整个送货的任务
↓
☕ 需要做过这一单子的运输团队
↓
☕ 运输团队需要记录路径(任务复杂)
↓
☕ 去到每个仓库(加载整个脚本文件)
↓
☕ 每个仓库的大门都需要大开(整个文件都要被加载)
↓
☕ 从材料的查找开始,一个个去找(脚本里的所有代码都要执行)
↓
☕ 然后再制作(处理订单)
↓
☕ 完成,整个送货任务结束,进程结束
↓
下次订单又要重新启动整个送货任务,重新开仓库,重新找材料

关键特点:
- 进程 = 整个送货的任务:不是车马,而是整个送货的任务
- 需要做过这一单子的运输团队:每次都要重新组织运输团队
- 运输团队需要记录路径:任务复杂,需要运输团队记住路径
- 没有固定的备货流程:没有路由系统,每个脚本都是独立的
- 每次都要重新开始:每次请求都要重新启动进程(整个送货的任务),重新加载文件
- 整个文件都要被加载:可能一个文件里面只跑一个函数,但还是要请求整个文件
- 同样的流程没有被记录和筛检:没有路由系统,没有固定的流程
- 所以等于每次都是新的:每次请求都是独立的,没有复用
Servlet 是什么?
☕ 黑水甲瓦法师:"Servlet 是我的代码仓库,专门用来做 CGI 这样的物流过程。它比 CGI 更完整,有生命周期管理,可以复用,但每次请求还是要重新处理整个送货任务。"
Servlet = 代码仓库,专门用来做 CGI 这样的物流过程:
- 是 Java 的 Web 处理技术:黑水甲瓦法师用来处理 Web 请求的技术
- 类似 CGI,但更完整:有生命周期管理、可以复用
- 专门用来做 CGI 这样的物流过程:实现类似 CGI 的功能,但更高效
- 每次请求还是要重新处理:虽然可以复用,但每次请求还是要重新处理整个送货任务
- 进程 = 整个送货的任务:需要做过这一单子的运输团队,运输团队需要记录路径,任务复杂
Servlet 时代的前后端模式:
🐍 大蟒蛇法师:"Servlet 时代(1990s)主要是传统模式,前后端不分离。那时候还没有灵狐法师(现代前端框架),所以黑水甲瓦法师直接返回 HTML 页面(JSP)。"
☕ 黑水甲瓦法师:"是的,在 Servlet 时代,我主要是用 Servlet + JSP 的方式,直接返回 HTML 页面,前后端不分离。那时候还没有灵狐法师,所以我不需要与灵狐法师合作。但 Servlet 技术本身可以支持前后端分离(提供 API),只是那时候前端技术还没成熟,所以主要是传统模式。"
关键理解:
- Servlet 时代(1990s) :主要是传统模式,Servlet + JSP,直接返回 HTML,前后端不分离
- Servlet 技术本身:可以支持前后端分离(提供 API),但那时候前端技术还没成熟
- 现代 Servlet(Spring MVC,2010s+):可以前后端分离,与灵狐法师合作,提供 REST API
- 前后端分离的时代:2010s+,现代前端框架(React/Vue/Angular)兴起,后端提供 API
问题:
- ❌ 每次订单都要重新启动整个送货任务,效率太低
- ❌ 需要做过这一单子的运输团队,运输团队需要记录路径,任务复杂
- ❌ 资源消耗大(每次都要启动新进程)
- ❌ 无法处理大量订单(高并发时性能瓶颈明显)
📜 第二代:改进的物流系统(PHP、ASP.NET)
时代背景
🐍 大蟒蛇法师:"后来有了改进的物流系统,比如 PHP 织布师的物流系统。进程(整个送货的任务)可以复用,但还是要重新准备。还有蓝盾法师的 ASP.NET 系统。"
特点:
- PHP:PHP 织布师的物流系统,进程(整个送货的任务)可以复用
- ASP.NET:蓝盾法师的物流系统,从彩色方块世界来的
- 可以复用资源:但每次请求还是要重新初始化
- 效率提升:比第一代快,但还不够
PHP 的改进:进程(整个送货的任务)可以复用
🧵 PHP 织布师:"我织布师也不是吃素的!我的送货团队早就养在厂里,随时待命。订单一来,运输马车立刻出发,省时又省马草。虽然每次还得亲自装货、一个仓库一个仓库跑,但这可比临时招人强多了。"
PHP 的工作方式(进程可以复用):
plain
第一次请求:
🛡️ 阿帕奇守护者:"启动 PHP 进程"
↓
🧵 PHP 织布师:"进程(整个送货的任务)准备好了"
↓
🧵 进程 = 整个送货的任务
↓
🧵 需要做过这一单子的运输团队
↓
🧵 运输团队需要记录路径(任务复杂)
↓
🧵 处理订单(一个个仓库去开)
↓
🧵 进程保留(整个送货的任务还在,运输团队没有遣散)
第二次请求:
🛡️ 阿帕奇守护者:"复用 PHP 进程"
↓
🧵 PHP 织布师:"进程(整个送货的任务)还在,但我需要重新装货..."
↓
🧵 重新初始化 PHP 环境(重新装货)
↓
🧵 需要做过这一单子的运输团队
↓
🧵 运输团队需要记录路径(任务复杂)
↓
🧵 处理订单(还是要一个个仓库去开)
↓
🧵 进程保留(整个送货的任务还在,运输团队没有遣散)

关键理解:
- 进程 = 整个送货的任务:不是车马,而是整个送货的任务
- 进程(整个送货的任务)一直在:PHP 进程可以保留,不需要每次都重新启动
- 同样的运输团队,并没有遣散,随时待命:进程可以复用,随时待命
- 需要做过这一单子的运输团队:每次请求还是要重新组织运输团队
- 运输团队需要记录路径:任务复杂,需要运输团队记住路径
- 执行一样的运输任务,就会识路:进程可以复用,可能有一些缓存或优化
- 但还是要一个个仓库去开:每次请求还是要重新加载和执行 PHP 脚本文件
与 CGI 的对比:
CGI(第一代):
plain
每次请求:
启动新进程(整个送货的任务) → 处理订单 → 进程结束
需要做过这一单子的运输团队,运输团队需要记录路径,任务复杂
整个送货任务用完就没了,运输团队遣散了
PHP(第二代):
plain
每次请求:
复用进程(整个送货的任务) → 处理订单 → 进程保留
需要做过这一单子的运输团队,运输团队需要记录路径,任务复杂
整个送货任务一直在,运输团队没有遣散,随时待命
改进:
- ✅ 进程(整个送货的任务)可以复用,不需要每次都重新启动
- ✅ 同样的运输团队,并没有遣散,随时待命
- ✅ 效率比第一代高
- ⚠️ 但每次请求还是要重新初始化(重新装货)
- ⚠️ 但还是要一个个仓库去开(重新加载和执行脚本文件)
- ⚠️ 但还是要需要做过这一单子的运输团队,运输团队需要记录路径,任务复杂
🐍 大蟒蛇法师:"所以说,从第一代到第二代,物流团队从'外包临工'进化成了'自家雇员',虽然搬货流程还不够自动化,但起码省去了每次重启团队的烦恼。"
🔄 第一代 vs 第二代:关键差异对比
🐍 大蟒蛇法师:"虽然第一代和第二代都是传统模式,但它们有一个关键差异:进程是否可以复用。让我用一个对照表来说明。"
| 特性 | 第一代(CGI/Servlet) | 第二代(PHP/ASP.NET) |
|---|---|---|
| 进程复用 | ❌ 每次请求都重新启动进程 | ✅ 进程可以复用,保留在内存中 |
| 运输团队 | 每次都要重新组织,用完就遣散 | 运输团队不遣散,随时待命 |
| 启动成本 | 高(每次都要启动新进程) | 低(复用已有进程) |
| 资源消耗 | 按需消耗,但启动成本高 | 持续占用,但响应更快 |
| 效率 | 低(每次都要重新开始) | 较高(进程复用带来效率提升) |
| 适用场景 | 订单很少的场景 | 订单频繁的场景 |
核心差异:
- 第一代:每次订单都要重新启动整个送货任务,进程用完就结束,运输团队遣散
- 第二代:进程(整个送货的任务)可以复用,运输团队不遣散,随时待命,但每次请求还是要重新初始化

第二代时代的前后端模式:
🐍 大蟒蛇法师:"第二代时代(2000s)主要是传统模式,前后端不分离。那时候还没有灵狐法师(现代前端框架),所以 PHP 织布师和蓝盾法师直接返回 HTML 页面。"
🧵 PHP 织布师:"是的,在 PHP 时代(2000s),我主要是直接返回 HTML 页面,前后端不分离。那时候还没有灵狐法师,所以我不需要与灵狐法师合作。PHP 技术本身可以支持前后端分离(提供 API),但那时候前端技术还没成熟,所以主要是传统模式。"
🛡️ 蓝盾法师:"虽然没人见过我的真身,但我的 ASP.NET 系统也是这样的。在 ASP.NET 时代(2000s),我主要是传统模式,直接返回 HTML,前后端不分离。那时候还没有灵狐法师,所以我不需要与灵狐法师合作。但 ASP.NET 技术本身可以支持前后端分离(提供 API),只是那时候前端技术还没成熟,所以主要是传统模式。"
关键理解:
- 第二代时代(2000s) :主要是传统模式,PHP/ASP.NET 直接返回 HTML,前后端不分离
- PHP/ASP.NET 技术本身:可以支持前后端分离(提供 API),但那时候前端技术还没成熟
- 现代 PHP/ASP.NET(2010s+):可以前后端分离,与灵狐法师合作,提供 REST API
- 前后端分离的时代:2010s+,现代前端框架(React/Vue/Angular)兴起,后端提供 API
📚 系列导航
系列名称 :Web API 演进史:从 CGI 到 FastAPI
(用物流系统比喻讲解 Web API 演进)
📝 片段1 结束
🔄 下一片段预告:
运输团队终于不用手动写地址了!REST API 标准登场,为物流世界带来了"送货协议"与"资源派发规则"。
前后端开始真正分工,一场现代物流革命悄然发生......