CHAPTER 01 / 自学试学版

从输入网址到点击保存:一次请求怎样走完?

读解释、检查证据、修订自己的设计。正文与参考记录可离线阅读,真实网络观察需要联网或启动本机服务。

导出包含第 0–7 章作答。导入会替换八章全部作答,包括文件中未包含的章节;建议先导出备份。

先修:第零章 · 核心学习无需安装

1.1 先把“看到了”和“保存了”分开

在笔记框里输入一句话,页面立刻出现新内容。你确实看到了它,但这句话在哪里?可能只在输入框里,也可能进入了浏览器本地存储,或者已送到某个服务。界面变化是观察,保存位置是需要证据支持的解释。

本章沿着一条消息往返,找出浏览器、应用和数据库各做了什么。你会现场观察公开课件的读取请求,再分析作者运行本机笔记服务时采集的写入记录。记录是一次已经发生的实验,不是你现在正在向云端提交数据。线上课件仍是静态页面,答案留在你的浏览器中。

学完应能回答:谁向谁发送了什么?响应能够说明什么?还需要什么证据,才能判断数据是否留下?

1.2 现场观察:浏览器怎样取得课件

打开固定示例 线上课件首页。在该标签页打开浏览器的开发者工具,选择 Network/网络,保持记录开启,再刷新页面。筛选 Doc/文档,找到地址对应首页的一行。手机不便打开工具时,可以先完成下节的记录阅读,现场观察留到电脑上做。

  1. 点开这一行,在 Headers/标头中找完整地址、Request Method 和 Status Code。
  2. 确认方法为 GET,再在 Response/响应中找 HTML 正文。它是浏览器用来构成页面的文件。
  3. 若看到缓存标记或 304,记录下来;可在工具打开时勾选 Disable cache/停用缓存,再刷新观察。拿不到页面时先检查联网和地址,不把环境失败当作概念错误。

这条路线是:浏览器请求页面 → 静态托管返回文件 → 浏览器解析并显示。200 表示这次请求成功处理;缓存也可能提供页面内容。它们都不能单独证明你的笔记被保存了,因为这次请求要的是课件文件。

判错题一:页面新增一行笔记,已经足以证明云端保存成功吗?

1.3 地址找到对象,方法表达意图

把 https://system-design-course-8nv.pages.dev/ 分开看:https 指明通信方式,中间的域名定位站点,最后的 / 是请求路径。路径未必对应磁盘上的同名文件,也可能由应用处理。

请求还有方法、标头和可能存在的正文。方法 GET 表达读取资源;本章笔记接口用 POST 表达创建笔记,并在正文里携带 {"title":"第一条笔记"}。这叫 JSON:用字段名和取值描述数据。方法说明意图,应用代码决定如何处理,不能只靠名字推断内部实现。

选读:DNS 和 TLS 在哪一步?

DNS 帮助把域名解析为连接所需的地址信息;TLS 用于验证通信对端并保护传输。浏览器可能复用已有解析结果和连接。本章的请求列表不能展示它们全部的内部过程,时序图只画职责,不伪装成抓到了每个步骤。HTTPS 保护传输,也不等于应用一定正确保存了数据。

1.4 完整往返:读列表,再创建一条笔记

现在换成课程提供的本机笔记服务。这里“服务端”是接收 HTTP 请求的程序,运行在你的电脑上;数据库也是本机 SQLite 文件。服务端不一定在云端,浏览器与它仍有明确的责任边界。

读取:浏览器 → GET /api/notes → 应用查询 SQLite
      浏览器 ← 200 与笔记列表 ← 应用返回查询结果

创建:浏览器 → POST /api/notes,正文包含 title
      应用校验 → 写入 SQLite 并提交 → 返回 201 与新笔记
      浏览器显示结果 → 再次 GET /api/notes 核查列表

读取让页面获得已有数据;创建才请求改变数据。本例约定:非空且不过长的标题通过校验,提交完成后返回 201。正文中的新笔记编号把这次响应与后来读取的对象连接起来。Network 只能直接给出请求和响应;“写入并提交”还要由已核查的实现与数据证据支持。

下面是作者真实运行服务后保存的记录。按顺序对照写入前、创建响应、写入后与重启后的数据。不要把记录里的日期、标题或结果当作当前网络状态;它说明这一次实验发生了什么,不保证任何未来请求都成功。

已采集的真实 HTTP 记录 · 不代表当前请求

采集时间(UTC):2026-10-04T22:31:19.578176+00:00。隔离临时数据库;仅使用虚构笔记;下面所有响应均来自实际运行。

1. 写入前读取 · GET /api/notes → 200
{
  "请求体": null,
  "响应": {
    "notes": []
  }
}
2. 合法创建 · POST /api/notes → 201
{
  "请求体": {
    "title": "第一条测试笔记"
  },
  "响应": {
    "note": {
      "id": 1,
      "title": "第一条测试笔记"
    },
    "storage": "sqlite"
  }
}
3. 写入后重新读取 · GET /api/notes → 200
{
  "请求体": null,
  "响应": {
    "notes": [
      {
        "id": 1,
        "title": "第一条测试笔记"
      }
    ]
  }
}
4. 直接提交空标题 · POST /api/notes → 422
{
  "请求体": {
    "title": ""
  },
  "响应": {
    "error": "标题需为 1–80 个字符的非空文本"
  }
}
5. 空标题拒绝后读取 · GET /api/notes → 200
{
  "请求体": null,
  "响应": {
    "notes": [
      {
        "id": 1,
        "title": "第一条测试笔记"
      }
    ]
  }
}
6. 直接提交超长标题 · POST /api/notes → 422
{
  "请求体": {
    "title": "测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测测"
  },
  "响应": {
    "error": "标题需为 1–80 个字符的非空文本"
  }
}
7. 拒绝请求后读取 · GET /api/notes → 200
{
  "请求体": null,
  "响应": {
    "notes": [
      {
        "id": 1,
        "title": "第一条测试笔记"
      }
    ]
  }
}
8. 服务重启后读取同一数据库 · GET /api/notes → 200
{
  "请求体": null,
  "响应": {
    "notes": [
      {
        "id": 1,
        "title": "第一条测试笔记"
      }
    ]
  }
}

写入和读取实现已与上述结果核对。每条记录仍只支持相应测试条件下的结论;不证明所有输入或故障均已覆盖。

可选:在自己的电脑上重复实验

在提供的项目目录运行 python3 demo_server.py,再打开 本机第一章。它使用 Python 标准库和 SQLite;若电脑没有 Python,可以继续使用上面的记录完成核心学习。服务只监听本机回环地址、没有账号功能,是教学实验,不是生产模板。

本机页面从同一个服务读取和创建笔记。刷新页面或重启服务不会删除已提交的 SQLite 数据;本章的学习答案仍由浏览器单独保存。关闭服务后请求会失败,已保存的数据不因此自动消失。公开课件没有这些写入接口。

1.5 错误提示只是起点,要查数据有没有改变

假设表单禁止空标题,点击保存时出现提示。若浏览器根本没发请求,这只证明表单拦住了输入。别的程序可以直接发送请求,所以应用收到数据后仍要校验。用户界面负责帮助输入,服务端负责守住自己承诺的数据规则。

查看记录中绕过表单的直接请求:发送空标题,再发送超过上限的标题。每次都要连接三份证据:请求确实发出,服务返回 422,前后数据库记录没有新增。实验区标明本例的长度上限。只看页面红字,甚至只看一个错误状态码,都少了数据核查。

判错题二:直接发送空标题得到 422,前后数据相同,能得出什么?

还要区分另一类问题:甲、乙分别打开同一条旧笔记,各自修改后保存,这是两个不同编辑发生冲突;甲没收到回复而再次发送原操作,才是同一操作重试。当前演示只实现创建与读取,不实现编辑冲突处理。后续会分别讨论,不能以“加重试”回答所有保存问题。

1.6 换个场景:收藏夹真的收藏了吗?

你设计一个跨设备收藏夹。点击星号后它立刻变亮;新设备暂时看不到收藏。请写出至少两个可能解释,画出你期待的读写路线,并选择下一项核查证据。不要直接断言服务故障,也不要把按钮颜色当作数据库记录。

提示一:把界面状态和保存状态分别列出来

星号由谁画亮?请求是否发出?两台设备是否读取同一个用户的数据?这些问题的答案还没有给定。

提示二:寻找能排除一个解释的证据

先查本次收藏请求和响应,再查返回的收藏编号及服务端记录。若有记录,再比较新设备的读取请求和身份;不要一口气猜测所有环节。

提示三:一种合格的参考推理

可能仅在本地改变颜色,也可能服务已保存而新设备读取了旧列表或不同账号。预期路线是“创建收藏 → 服务校验并保存 → 返回编号 → 另一设备请求列表”。我先检查创建请求,再按结果决定查写入还是读取。其他方案也可成立,只要证据能支持结论,并保留尚未排除的解释。

勾选只记录自评。若无法指出具体证据,回到对应小节补充答案,再带着这条读写路线进入需求设计。

选读范围:带着一个问题读原资料