Day 7 - 复盘日:把 Week 1 的六天连成一张图
不许翻前六天的讲义。先凭记忆写,写完再对照订正。订正的地方用红色或加粗标出来——那些就是你真正的知识缺口,下周会再考。
如果某一题完全写不出来,不要跳过。写下「我不会」,然后去看讲义,再用自己的话重写一遍。
🗺️ 第一件事:画出「一个 HTTP 请求的一生」(约 40 min)
这是本周最重要的产出。把六天学的东西,串成一条线。
任务
在 src/07-week1-review/request-lifecycle.md 里,用文字或 mermaid 画出下面这个过程,每一步标注它对应 Day 几学的内容:
场景
一个德国用户在浏览器输入 https://www.supergood-tech.de/de/day/1/,回车。你的 Node 服务器上发生了什么?
要覆盖这些环节(顺序你自己排):
- 浏览器发出的那段文本长什么样
- TCP 连接建立后,谁通知了 event loop
- event loop 在哪个 phase 取出这个事件
- 你的 handler 在哪个线程上跑
- handler 里
await数据库时,主线程去干嘛了 - 如果 handler 里有 2 秒 CPU 计算,会发生什么,该怎么办
- 响应体 100MB 时,该怎么写出去
- 想吃满 4 核,该用什么
- 响应报文长什么样,必须有哪几个 header
写完之后自查:这九个环节你标出了几个 Day?
参考答案的对应关系(不是完整答案,只是给你对一下 Day 编号):
| 环节 | 对应 |
|---|---|
| 请求报文格式、状态码、header | Day 6 |
| libuv 通知 → poll phase 取出 | Day 2 |
| handler 在主线程跑,await 时让出 | Day 1 |
| CPU 计算卡住全场 → worker_threads | Day 5 |
| 大响应体用流,别拼字符串 | Day 3 |
| 吃满多核 → cluster 多进程 | Day 4 |
面试官问「你了解 Node 吗」,背 API 的人说「我用过 Express」;能画这张图的人,直接进入下一轮。
更重要的是:这张图在 C#、Java、Go 里结构完全一样,只有第 3、4 步不同(它们用线程池,不用 event loop)。你画的是「后端服务器」,不是「Node 服务器」。
✍️ 第二件事:六张概念卡默写(约 60 min)
写在 src/07-week1-review/concept-cards.md。每张卡片必须包含三部分:通用定义(不绑定语言)、Node 里的样子、其他语言里的样子。
卡片 1:并发模型(Day 1)
- 并发和并行的区别,用一句话
- 三种并发模型各自的取舍(多线程 / 事件循环 / 协程)
- 为什么说 Node 的模型适合 I/O 密集,不适合 CPU 密集
卡片 2:事件循环(Day 2)
- 六个 phase 的顺序,以及你只需要记住的三站是哪三站
- nextTick 和 microtask 在什么时候清场,它们属于 phase 吗
setTimeout(fn, 0)和setImmediate(fn),顶层调用时谁先?I/O 回调里调用时谁先?为什么不一样
卡片 3:流与背压(Day 3)
- 为什么 2GB 文件不能用
readFileSync - 背压是什么,
write()返回 false 时该做什么 - 字节和字符的区别,一个中文字在 UTF-8 里几个字节
卡片 4:进程模型(Day 4)
- 进程和线程的区别(内存、沟通、崩溃影响三个维度)
- exec / execFile / spawn / fork 各自的场景,以及两颗炸弹是什么
- cluster 多个进程共享同一个端口的原理
卡片 5:线程与共享内存(Day 5)
- worker_threads 和 cluster 的三个区别
- 拷贝 / 转移 / 共享三种传数据方式,各自什么时候用
- 什么是竞态条件,Atomics 在防什么
- 决策表至少 5 行:什么时候用 worker / cluster / child_process / 什么都不用
卡片 6:HTTP(Day 6)
- 请求报文的四个部分,那个空行的作用
- 五类状态码,401 和 403 的区别
- 幂等的定义,以及它和客户端重试的关系
- Content-Length 和 chunked 的区别
🔍 第三件事:给自己这周的代码做一次 review(约 40 min)
打开你这周写的所有代码(src/01- 到 src/06-),用「别人写的代码」的眼光看一遍。把发现写在 src/07-week1-review/code-review.md。
Review 清单(逐条检查)
| 检查项 | 为什么重要 | 对应 Day |
|---|---|---|
有没有地方用了 readFileSync 读可能很大的文件 | 内存炸弹 | Day 3 |
有没有 body += chunk 这种攒字符串的写法,且没有大小上限 | 上传攻击面 | Day 3 / 6 |
| 有没有创建了 worker / child_process 但忘了 terminate / kill | 进程不退出 | Day 4 / 5 |
| 有没有在主线程做超过 100ms 的同步计算 | 卡住所有请求 | Day 1 / 5 |
错误有没有被吞掉(空的 catch、没监听 error 事件) | 问题被藏起来 | 全部 |
用 exec 的地方,命令里有没有拼接外部输入 | shell 注入 | Day 4 |
Content-Length 有没有用 .length 而不是 Buffer.byteLength | 中文截断 | Day 6 |
| 变量名和函数名,一周后的你看得懂吗 | 可维护性 | — |
产出要求
每发现一个问题,写成这个格式:
## 文件:src/03-streams-buffer/ex2.ts 第 18 行
**问题:** 用 readFileSync 读了一个可能 2GB 的文件
**后果:** 内存会被吃光,进程崩溃
**改法:** 改成 createReadStream + pipeline
**我当时为什么这么写:** 只想着能跑通,没想文件会变大
最后一行最重要。记录当时的想法,才能发现自己的思维盲区。
如果一个问题都没发现,那说明 review 得不够仔细——再看一遍,特别看错误处理和资源释放。
📊 第四件事:补对照表 + 自测 20 题(约 40 min)
4.1 补跨语言对照表
打开 roadmap.md,找到顶部的「后端概念跨语言对照表」。这周学到的东西,至少补三行:
- 运行时与并发模型 行 —— 补一句你自己的理解(Day 1 / 5)
- 流式 I/O 行 —— 补一句(Day 3)
- 新增一行 HTTP 服务器 —— 填 Node / C# / Java / Python / Go(Day 6 讲义里有)
要求:补的内容必须是你亲手验证过的,不是抄讲义。抄的东西记不住。
4.2 自测 20 题(闭卷,写在 src/07-week1-review/self-test.md)
基础题(每题 1 分)
- 并发和并行的区别是什么?
- event loop 的六个 phase,哪三个最重要?
process.nextTick和Promise.then,谁先执行?- 为什么递归调用
process.nextTick会饿死 event loop? - Buffer 和 String 的区别是什么?
write()返回false意味着什么?你该做什么?pipe()和pipeline()的区别?该用哪个?- 进程和线程,在「内存」这个维度上有什么区别?
exec的maxBuffer是什么?超了会怎样?- cluster 的多个 worker 怎么能监听同一个端口?
理解题(每题 2 分)
- 为什么说 worker_threads 不是 cluster 的升级版?
- postMessage 的「转移」和「共享」有什么区别?各自什么时候用?
- 什么是竞态条件?用一个具体例子说明。
- HTTP 请求报文的四个部分是什么?那个空行为什么必须有?
- 401 和 403 的区别?
- 为什么表单校验失败不该返回 500?
- 什么是幂等?POST 和 PUT 哪个幂等?
- 什么时候必须用 chunked 而不是 Content-Length?
综合题(每题 5 分)
- 场景题:你的 API 有一个
/report接口,要生成一个 PDF,耗时约 3 秒(纯 CPU)。上线后用户反馈「点了报表,整个网站都卡住了」。用这周学的知识完整解释原因,并给出两个不同层次的解决方案。 - 场景题:你的 API 有一个
/export接口,要导出一个 2GB 的 CSV。目前的实现是先在内存里拼好字符串再返回。说出至少三个问题,并给出改法。改完之后,响应头会有什么变化?
评分:满分 36。低于 25 分,下周开始前先把错题对应的那天重看一遍。
🎯 Week 1 结算与 Week 2 预告
这周你从「不知道」到「能讲清楚」的东西
| Day | 主题 | 核心收获 |
|---|---|---|
| 1 | 并发模型 | 一个服务员怎么招呼一千桌客人 |
| 2 | event loop | 他的巡场路线和清场顺序 |
| 3 | Stream / Buffer | 2GB 的菜怎么端才不砸锅 |
| 4 | 进程模型 | 一个人不够时怎么开分店 |
| 5 | worker_threads | 店里加操作台,以及什么时候不该加 |
| 6 | HTTP | 客人递的那张纸条长什么样 |
你现在知道一个后端服务器从「接到字节」到「发出字节」的完整链路,以及每一环可能出什么事。
这是所有后端知识的地基。接下来学的东西(框架、数据库、缓存、部署)都是盖在这上面的。
Week 2 预告(Day 8–14):服务端 TypeScript + HTTP 语义深入
- TypeScript 在服务端真正有用的部分:泛型、discriminated union 与类型收窄(你的水平测试 G2 题)、
unknownvsany - 用 zod 做运行时校验——为什么「类型」和「校验」是两件不同的事
- HTTP 语义深入:幂等、内容协商、缓存头
- 统一错误格式 RFC 9457 problem+json 正式落地
- 产出:把 Day 6 的裸 http API 加上 zod 校验和统一错误体
提交今天的产出
git add -A
git commit -m "docs: week 1 review"
✅ 复盘日自检
- 画出了「一个 HTTP 请求的一生」,九个环节都标了 Day 编号
- 六张概念卡全部默写完,每张都有「通用定义 + Node + 其他语言」三部分
- 对本周代码做了 review,至少找出 3 个问题并写清了改法和当时的想法
- roadmap 对照表补了至少 3 行,内容是自己验证过的
- 自测 20 题做完并打分,低于 25 分的部分已经安排重看
- 今天的产出已经 commit