综合练习
这一课你将能做到
- 独立用 DevTools Network 与 curl 完成「打开
/tracks → 读到 /api/tracks」的全链路记录:方法、状态码、关键头、协议版本、缓存迹象
- 按现象速查表定位 401/403、CORS、502、数据陈旧、慢 TTFB 五类问题,说出每类该进 Nginx / Spring / Redis 哪条轨道深挖
- 交付三件套:一张 ≥5 行的请求记录表 + 一段「HTTPS 在哪终止、JSON 谁生成」的链路说明 + 一条可落地的缓存改进建议
为什么要学
前面每课拆开讲,线上故障却是搅在一起的:一个「页面打不开」可能同时涉及 502、缓存、Cookie。会读 Network 里的一行,等于会读半条 Web 链路——这是后端与全栈的日常肌肉,也是「从输入 URL 到页面展示」面试题的实操版。
本课没有新概念,只有可重复的流程。做完这五个任务,本 track 的 12 课就收束成你自己的排错清单,而不是一堆零散知识点。
先建立图像
你的固定排错镜头(背下来,每次都用同一套):
1. 复现 → 无痕窗口 + Preserve log + 硬刷新
2. 定位 → 找 document 与关键 XHR/fetch 请求
3. 顺序 → 先 Status → 再 Request/Response Headers → 再 Timing → 最后 Preview
4. 二分 → 同一请求 Copy as cURL,终端复现(排除浏览器独有因素)
5. 分层 → TLS/Nginx → 应用 → DB/Redis → 客户端缓存
现象 → 先查什么:
| 现象 | 先查 |
|---|
| 502 Bad Gateway | upstream 存活?端口对?Nginx error.log |
| 401 / 403 | Cookie/Bearer 带了吗?角色对吗?(401 登录、403 权限) |
| CORS 红字 | OPTIONS 过没过?Allow-Origin 有没有?——先用 curl 看是不是其实是 5xx |
| 数据陈旧 | 浏览器缓存 → Nginx → Redis → DB 逐层核对(应用缓存课演习表) |
| 慢 TTFB | 应用日志、慢 SQL、缓存命中、冷启动 |
| 混合内容 | HTTPS 页面拉了 http:// 资源 |
跟着做
任务 A:页面加载链全记录
- 无痕窗口打开
https://coderoadmap.cn/tracks(或本地 localhost:3000/tracks)
- F12 → Network → 勾 Preserve log → Ctrl+Shift+R 硬刷新
- 填这张表(每格都要动手看,不许猜):
类型 方法 路径 状态 Content-Type Protocol Size/缓存
document GET /tracks ___ text/html ___ ___
stylesheet GET /_next/static/...css ___ text/css ___ ___
script GET /_next/static/...js ___ ___ ___ ___
xhr/fetch GET /api/tracks ___ application/json ___ ___
(再补 1 行:字体/图片/其它 API)
- 点
api/tracks → Timing 标签:DNS、TLS、Waiting (TTFB)、Content Download 各占多少?
任务 B:curl 对照实验
# 状态码 + 总耗时一锅端
curl -w "\ncode:%{http_code} time:%{time_total}s size:%{size_download}B\n" \
-o tracks.json -s -H "Accept: application/json" \
https://coderoadmap.cn/api/tracks
# 详情与 404 形状
curl -i https://coderoadmap.cn/api/tracks/spring-boot-essentials
curl -o /dev/null -s -w "%{http_code}\n" https://coderoadmap.cn/api/tracks/not-exist-slug-xyz
# 本机 Spring(若还开着前面的 demo)
curl -i http://localhost:8080/api/notes
确认三件事:tracks.json 能被解析成合法 JSON;不存在资源返回 4xx 而不是 500;浏览器和 curl 看到的状态码一致。
任务 C:缓存三层实验
- 普通刷新两次:
api/tracks 是 304、disk cache 还是真实下载?静态 JS 呢?
- 勾选 Disable cache 再刷新:总耗时差多少?TTFB 变化说明什么?
- 若响应有
X-Cache-Status,记下 HIT/MISS;连续两次刷新对比
- 一句话对比:
/_next/static 与 /api/tracks 的缓存策略差异及原因
任务 D:安全与会话抽样
- Application → Cookies:会话票是否 HttpOnly + Secure?SameSite 是什么?
- 任选一个需登录的请求:Request Headers 里
cookie: / authorization: 出现了吗?与未登录时对比
- 地址栏是 https 吗?锁图标里证书有效期还剩多久?
- 思想实验:如果这个站改成
http:// 明文部署,哪三类风险立刻出现?(HTTPS 课的表)
任务 E:CORS 与协议思想题
- 写清楚:生产同域部署时为什么几乎不痛 CORS?(Nginx 把页面和
/api 拼成同源)
- 本地
:3000 → :8080 场景,Network 里应先找哪一类请求?(OPTIONS 预检)
- 用 Protocol 列确认本站主域与 API 的协议;若有第三方资源,它们的协议一致吗?
交付物自检
讲清楚要点
- 因为故障是跨层的,所以固定流程比「感觉改一改」可靠——先观测再改配置;每次都用同一套镜头,团队里别人才能接手你的排查。
- 因为浏览器多了安全层与缓存层,所以 curl 对照能快速二分——curl 通、浏览器不通 → CORS/Cookie/混合内容;两边都不通 → 服务端问题。
- 因为状态码是摘要,所以红字先读 Status 再谈别的——502 别先怪 React,404 别先查数据库,方向错了全是白费。
- 因为缓存分层,所以「清缓存」必须说清清哪一层——浏览器强刷、CDN purge、Nginx 重启、Redis DEL 是四个不同动作(应用缓存课)。
- 因为 Timing 分段,所以「慢」必须说清慢在哪段——DNS/TLS 慢查网络与证书配置;TTFB 慢查应用与 DB;下载慢查体积与压缩。
- 因为本 track 与 Nginx/Spring/Redis 咬合,所以这里是跳板不是终点——部署问题深挖 nginx-essentials;API 细节深挖 spring-boot-essentials;会话与缓存深挖 redis-essentials。
你可能会懵的地方
-
Preserve log 到底解决什么?
页面跳转或重定向会清空 Network 列表,勾上它保留完整跳转链——排「登录后又弹回登录页」这类重定向循环必备。
-
为什么无痕窗口和普通窗口表现不一致?
扩展、旧 Cookie、旧缓存、Service Worker。排障一律先无痕复现,否则你可能在修一个不存在的问题。
-
Copy as cURL 太长,要全贴吗?
复现问题优先全贴(头都在)。日常调试保留 URL、方法、关键头(Authorization、Content-Type、Cookie、Origin)即可。
-
页面上根本看不到 api/tracks 请求?
页面可能 SSR 时已把数据嵌进 HTML(document 响应里搜数据关键词),或接口名不同。任务 A 就记录 document 与静态资源,另找任意 JSON XHR 练手,结论不变。
-
五个任务做完能算掌握了吗?
能独立不看本课完成请求表 + 定位三类以上现象,就算达标;达不到就回对应课重做「跟着做」——这本就是回滚地图。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 只看 Console 红字字符串就下结论 | CORS 报错可能掩盖 5xx,文案不指向根因 | 打开 Network 看失败请求的状态、头与 Timing |
| 一慢就给前端加 loading 动画 | 慢因在 TTFB,loading 只是遮羞布 | Timing 分段定位:DNS/TLS/TTFB/下载各归各层 |
| 缓存问题只会让用户 Ctrl+F5 | 只清了浏览器层,Nginx/Redis 原样 | 按层失效 + 修 Cache-Control 策略 |
| 综合练习只打勾不写表 | 两周后全部忘光 | 留下可复习的请求表与结论句,成体系内化 |
| 把本课当新概念通宵速成 | 本课是体检清单不是知识课 | 缺哪课回哪课的「跟着做」补实操 |
卡点急救
- Network 里找不到 API 请求:确认筛选器没开着 XHR/Doc 单一过滤;确认页面数据不是 SSR 内嵌(在 document 响应的 Preview 里搜关键词);本地环境检查前端代理配置是否把
/api 转发了。
- curl 与浏览器状态码不一致:两头分别
curl -v 与 Network → Copy as cURL 逐头 diff——多数差异在 Cookie、Authorization、Origin 三个头上;也有服务器按 UA 区分行为的,保留完整头再测。
- Timing 里 Waiting (TTFB) 占了绝对大头:慢在后端。顺着「应用日志 → 慢 SQL(EXPLAIN)→ Redis 命中率」查;若 TTFB 只在第一次慢,是冷启动/首次建缓存,考虑预热。
面试常问
-
「从输入 URL 到页面展示」完整流程?
DNS 解析 → TCP 握手 →(TLS 握手)→ 发 HTTP 请求(方法/路径/头)→ Nginx 反代 → 应用(Spring 查 MySQL/Redis)返回状态码+头+body → 浏览器解析 HTML → 逐个请求 CSS/JS/图片/API → 渲染。要点:多次 HTTP 交换、无状态靠 Cookie 补、HTTPS 在边缘终止、缓存可能让部分请求根本不发出。
-
线上用户反馈「页面显示的数据是旧的」,你怎么排查?
按层:① 浏览器层——无痕窗口复现,看是否强缓存(disk cache);② 网关层——curl 绕过浏览器看 Nginx 是否返回旧值(X-Cache-Status);③ 应用层——直连 8080 看接口值,Redis 里该键是否旧值未失效;④ 数据层——核对 DB 是否真的已更新、读写分离延迟。每层给出验证命令,而不是「重启试试」。
-
如何向面试官证明你真的会排查一个 502?
说清证据链:Nginx error.log 中 connect() failed 或 upstream prematurely closed → 前者查 Spring 进程存活与端口(netstat/ps),后者查 OOM 与超时(dmesg、GC 日志)→ 修复后用 curl 验证状态码恢复,并补上 upstream 健康检查与告警。突出「日志证据 → 假设 → 验证」的闭环。
自测三问
- 写出你的五步排错镜头(可与「先建立图像」对照,用自己的话)。
- curl 通、浏览器报 CORS 时,下一步打开 Network 的哪类请求?它最常见的两种失败形状是什么?
- 交付物三件套是什么?你的缓存改进建议具体改哪一层、预期收益怎么验证?
小结一句话
会读 Network 一行,等于会读半条 Web 链路——用固定镜头 + curl 二分 + 分层定位,把 12 课收成可重复的排错肌肉。
延伸