综合练习
复现 CodeRoadMap 生产反代拓扑。
综合练习
这一课你将能做到
- 在测试机按
deploy/nginx/test.conf.example 落地配置,完成 nginx -t → reload,并把域名指到本机
- 联调 Spring Boot
:8080 与 Next :3000,用验收表验证 301、页面、/api、安全头、上传体积
- 根据 502/404/重定向循环/WebSocket 症状定位问题,并写清「为何不把 8080/3000 直接暴露公网」
为什么要学
前面每一课拆开讲:结构、静态、反代、双 upstream、TLS、安全头、缓存、均衡、Ingress。
本课把它们 串成一次可演示的预发拓扑,对照 CodeRoadMap 生产思路做 smoke test。
能独立完成联调与排错,才算本 track 闭环;否则配置知识停留在「看过示例」。
先建立图像
验收目标拓扑(test)
浏览器 → http://test… ─301→ https://test…
│
Nginx:443
├─ /api/* → 127.0.0.1:8080 Spring Boot
└─ / → 127.0.0.1:3000 Next.js
清单:跳转 ✓ 页面 ✓ JSON API ✓ 安全头 ✓ 上传不 413 ✓
| 阶段 | 你要完成的事 |
|---|
| 前置 | 后端、前端进程健康 |
| 部署 | test conf 进 conf.d,证书/域名就绪 |
| 验收 | 表格五类检查 |
| 排错 | 对照速查表与日志 |
| 反思 | 公网暴露面与扩展项 |
跟着做
步骤 1:启动后端与前端
# 终端 1 — backend
cd backend && ./mvnw spring-boot:run # 监听 :8080
# 终端 2 — platform
cd platform && npm run dev # 监听 :3000
直连验收:
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8080/tracks
curl -sS -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/
两者都应是健康状态码(按你环境可能是 200)。上游挂着再开 Nginx,否则必 502。
步骤 2:部署 test 配置
sudo cp deploy/nginx/test.conf.example /etc/nginx/conf.d/coderoadmap-test.conf
编辑:
server_name 与 DNS/hosts 一致(如 test.coderoadmap.cn)
- 取消注释并填写
ssl_certificate / ssl_certificate_key
- 确认 upstream 仍指向本机 3000/8080(Docker 则改服务名)
sudo nginx -t
sudo systemctl reload nginx
hosts 示例:127.0.0.1 test.coderoadmap.cn。Compose 路线见 docker-compose。
步骤 3:跑验收表
| 检查项 | 操作 | 期望 |
|---|
| HTTP 跳转 | curl -I http://test…/ | 301 → https |
| 页面 | 浏览器打开 /tracks/nginx-essentials | Next 渲染正常 |
| API | curl -k https://test…/api/tracks(自签时) | JSON 列表 |
| 安全头 | DevTools 响应头 | nosniff、CSP 等存在 |
| 上传 | 管理端或接口 POST 小文件 | ≤20m 不 413 |
把 access.log 里一条 /api/ 记录截图或抄进笔记。
步骤 4:故障注入与恢复
# 停掉 backend(方式依你启动手段而定),再访问 /api/tracks
# 应看到 502;error.log 含 upstream 连接失败一类信息
# 恢复 backend 后再测,应回到 200
再故意把 proxy_pass 尾斜杠改错(改完务必能改回),观察 /api 404,强化反代课记忆。
步骤 5:排错速查(贴在显示器旁)
502 Bad Gateway → upstream 未监听 / 端口错 / 防火墙 / SELinux
404 on /api/foo → proxy_pass 尾 / 与 location 前缀不匹配
重定向循环 → X-Forwarded-Proto 未设或后端错误强制 https
WebSocket / HMR 失败 → 缺 Upgrade / Connection upgrade
413 Request Entity → client_max_body_size 过小
证书错误 → 路径、链、server_name、未 reload
sudo tail -n 100 /var/log/nginx/error.log
sudo tail -n 50 /var/log/nginx/access.log
步骤 6:扩展可选与复盘写作
- 复制 admin server:
root + try_files + /api/
limit_req_zone 保护登录(与 Redis 限流互补)
- 草拟等价 Ingress YAML(ngx-k8s)
必写(约 200 字):为何生产不让 :8080/:3000 直接公网暴露?
提示:TLS 集中、路径合流、安全头、减少攻击面、前端同源。
讲清楚要点
- 因为 Nginx 只转发,所以联调顺序是上游先活、再 reload 入口——否则满眼 502。
- 因为 test 与 prod 结构同构,所以预发验过的路径语义可迁到生产——差在域名、证书、加固强度。
- 因为验收要可观察,所以用 curl、DevTools、日志三件套——不要只「我觉得打开了」。
- 因为故障注入能暴露真实依赖,所以练习里要主动停 upstream——建立肌肉记忆。
- 因为尾斜杠与转发头是高频坑,所以综合练习必须再踩一次并修回——纳入检查清单。
- 因为安全是边界属性,所以验收包含头与跳转,而不只是 200——「能打开」≠「可上线」。
- 因为后续还有容器与 K8s,所以本课结论应迁移:改的是载体,不是双 upstream 产品拓扑——门岗可换,分流不变。
你可能会懵的地方
-
curl -k 是什么?
忽略证书校验,仅用于自签实验。生产验收应使用受信任证书,去掉 -k。
-
页面 200 但 API 失败?
分别测 location / 与 /api/。可能只是 backend 挂了或剥路径错误;Next 仍可能返回壳页面。
-
本机已有站点抢 80/443?
换端口做实验,或停用冲突 server;看 nginx -T 输出确认默认 server。
-
练习是否要上真实 Let's Encrypt?
有公网域名时建议走一遍;纯本地可用 mkcert。关键是走完「证书路径写入 conf → -t → reload」。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 未开上游就验收 Nginx | 全是 502,误判配置 | 先 curl 直连 8080/3000 |
-t 失败仍 reload | 配置未更新或服务异常 | 修到 successful 再 reload |
| 只看浏览器,不看 error.log | 猜原因 | 日志 + curl -I |
| 验收通过却保留错误 proxy_pass 实验 | 下次部署踩坑 | 实验后立即恢复并再测 |
| 公网映射 8080「图省事」 | 绕过 TLS 与安全头 | 只暴露 80/443 |
自测三问
- 写出本课验收表中至少四项检查及期望结果。
- 出现 502 时,你的前三个排查动作是什么?
- 用自己的话说明:双 upstream + 仅暴露 Nginx,对 Spring Boot / Next 部署意味着什么?
小结一句话
综合练习的目标是:独立复现 CodeRoadMap 双 upstream 预发拓扑,并用清单与日志证明它正确。
官方延伸