综合练习
这一课你将能做到
- 独立画出 Spring Boot + MySQL + Redis + Nginx + Docker 技术栈的完整生产部署架构图
- 用最小 DevOps 工具链 checklist 逐项验收一个项目的上线准备度
- 从零把一个新项目推上线:买服务器 → 容器化 → 配 Nginx+HTTPS → 接 CI/CD → 配监控
为什么要学
前 11 课每课一个工具,学的时候都懂,真到「给我把这个项目部署上线」的时候却无从下手——因为知识是点状的,没连成线。这一课就是「串线」:把所有工具按真实工作顺序组装成一条完整链路,并用 checklist 的方式固化下来,以后每接一个新项目照着走一遍即可。
人话:前面学的是一个个招式,这一课是连贯套路。面试官问「你讲讲你们项目的部署架构」,你能从用户请求讲到 CI/CD 流水线再讲到监控告警,这一课就算没白学。
先建立图像
最终架构全貌(一台云服务器的最小生产方案):
用户
│ HTTPS :443
▼
┌─────────────────┐
│ Nginx 容器 │ TLS 卸载 / 静态资源 / 反代 / 限流
└────────┬────────┘
│ :8080 (容器内网)
▼
┌─────────────────┐
│ Spring Boot 容器 │ 业务逻辑 / Actuator 健康检查
└────┬────────┬───┘
│ │
:3306 ▼ ▼ :6379
┌──────────┐ ┌──────────┐
│ MySQL 容器│ │ Redis 容器│ 数据卷持久化
└──────────┘ └──────────┘
CI/CD 链路:
git push main → GitHub Actions → 测试 → 构建镜像 → 推 ACR
→ SSH 到服务器 → compose pull && up -d
→ 健康检查 → 通知
跟着做
步骤 1:上线前 Checklist(逐项打钩)
□ 服务器篇
□ 云服务器已购买,安全组只放行 22/80/443
□ SSH 用密钥登录,已禁用 root 密码登录
□ 创建了普通用户 appuser 并配好 sudo
□ 应用篇
□ Dockerfile 是多阶段构建,镜像 <200MB
□ 容器内非 root 运行,配了内存限制
□ application-prod.yml 里没有任何明文密码(走环境变量)
□ /actuator/health 健康检查接口可用
□ 数据篇
□ MySQL 绑定容器内网,数据挂 volume
□ Redis 设置了 requirepass,数据挂 volume
□ 配置了数据库定时备份(crontab + mysqldump)
□ 网关篇
□ Nginx 配置了 HTTPS(证书自动续期已验证)
□ HTTP 301 跳 HTTPS
□ proxy_set_header 四件套齐全
□ 敏感接口配了限流
□ 流水线篇
□ push main 自动触发构建+部署
□ 密钥全部在 GitHub Secrets,代码零硬编码
□ 部署后有健康检查,失败流水线标红
□ 可观测篇
□ 应用日志落盘且配了切割
□ 有最简单的监控(至少能收到「服务挂了」的通知)
步骤 2:数据库备份脚本(checklist 里最容易漏的)
#!/bin/bash
# /opt/scripts/backup.sh —— 每天凌晨 3 点执行
set -euo pipefail
BACKUP_DIR=/opt/backups
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p "$BACKUP_DIR"
docker exec mysql mysqldump -umyuser -p"$DB_PASSWORD" mydb \
| gzip > "$BACKUP_DIR/mydb_$DATE.sql.gz"
# 只保留最近 14 天
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +14 -delete
echo "备份完成: mydb_$DATE.sql.gz ($(du -h $BACKUP_DIR/mydb_$DATE.sql.gz | cut -f1))"
# 注册到 crontab
crontab -e
# 加一行:
0 3 * * * DB_PASSWORD='Str0ng!Pass' /opt/scripts/backup.sh >> /var/log/backup.log 2>&1
# 备份不演练等于没备份:实测恢复
gunzip -c /opt/backups/mydb_xxx.sql.gz | docker exec -i mysql mysql -umyuser -p mydb
步骤 3:最小监控——服务挂了自动通知
不用上 Prometheus,一个 cron 脚本 + 一个 Webhook 就能兜住底线:
#!/bin/bash
# /opt/scripts/watchdog.sh —— 每分钟检查一次
if ! curl -sf -m 5 http://localhost:8080/actuator/health > /dev/null; then
curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"msgtype":"text","text":{"content":"[告警] myapp 健康检查失败,请立即处理"}}'
fi
# crontab 加一行
* * * * * /opt/scripts/watchdog.sh
步骤 4:一次完整的上线演练(计时挑战)
目标:假设服务器被误删,从零恢复到服务可用,30 分钟内完成。
- (5 min)Terraform apply 重建服务器,或控制台购买新机
- (5 min)Ansible playbook 跑一遍:装 Docker、配用户、拉代码
- (2 min)
docker compose up -d,MySQL/Redis 数据卷自动挂载(数据没丢因为走了云盘/备份)
- (3 min)恢复最新数据库备份
- (5 min)配 Nginx + certbot 申请证书
- (5 min)
curl https://api.example.com/actuator/health 验证
- (5 min)检查 watchdog、备份 crontab 是否就位
能跑通这套流程,说明你的所有基础设施都已「代码化」,不怕任何机器级别的故障。
步骤 5:常见面试场景推演
- 「流量翻倍怎么办?」→ Nginx 后挂两台 Java 容器,
upstream 配负载均衡;再往上就加服务器,Nginx 单独一台。
- 「数据库慢了怎么办?」→ 先慢查询日志定位,加索引;热点数据进 Redis;再不够读写分离。
- 「怎么做到发布不中断?」→ 两台 Java 实例 + Nginx upstream,滚动重启:先下一台(Nginx 自动摘除),更新完起了再更另一台。
讲清楚要点
- checklist 比记忆可靠:再熟的手也会漏步骤。把上线流程固化成 checklist 和脚本,每次照着走,出错率趋近于零——这是航空业和医学界的成熟实践,运维同样适用。
- 数据 > 应用:容器、代码、配置都可以重建,唯有数据库里的数据不可再生。备份必须有、必须自动、必须定期演练恢复。
- 监控的底线是「服务挂了有人知道」:完善的可观测体系(Prometheus + Grafana + 日志聚合)可以后面补,但健康检查 + 告警通知是第一天就要有的。
- 能重建的环境才是你的环境:把所有配置代码化(Terraform/Ansible/Compose),做到「机器随便换,30 分钟满血复活」,才算真正掌握了这套技术栈。
- DevOps 是持续改进:今天的土办法(watchdog 脚本)明天换成专业方案(Prometheus),没问题。先跑起来,再逐步优化,比一步到位但迟迟不上线强。
你可能会懵的地方
-
一台服务器跑所有容器,靠谱吗?
对个人项目和小流量业务完全够用(2 核 4G 能扛日活几千)。关键是要意识到单点风险并做好准备:数据备份、镜像在仓库、配置代码化,挂了能快速重建。流量上来后再拆。
-
什么时候该上 Kubernetes?
当你需要管理 10 台以上服务器、要求自动扩缩容、服务数量多到 compose 管不过来时。一台到三台机器,Docker Compose 是性价比最高的方案,不要为简历上 K8s。
-
监控方案怎么选?
起步:watchdog 脚本 + 钉钉/飞书 webhook(本课方案);进阶:Prometheus + Grafana(指标)+ Loki(日志);云服务:直接买云厂商的云监控,省心但贵。
-
备份要不要异地?
要。备份文件还在同一台机器上,机器丢了备份也没了。最低成本方案:备份脚本加一步 ossutil cp 或 aws s3 cp 同步到对象存储。
错法对照
| 错法 | 问题 | 正解 |
|---|
| 上线靠脑子记步骤 | 总有一步会漏 | checklist + 脚本固化 |
| 备份从不演练恢复 | 真出事才发现备份是坏的 | 每月至少恢复演练一次 |
| 监控只盯应用不盯磁盘 | 磁盘写满服务雪崩 | watchdog 里加 df 检查 |
| 出事才想回滚方案 | 手忙脚乱 | 镜像带 sha tag,回滚=改 tag 重启 |
| 一套配置打天下 | dev/prod 混用出事 | profile + env 文件分离环境 |
卡点急救
- 上线后发现容器互相连不上:检查 compose 里服务名拼写、
depends_on 顺序;docker compose logs mysql 看数据库是否初始化成功。
- HTTPS 配好了但浏览器提示混合内容:前端代码里写了
http:// 开头的 API 地址,全部改成相对路径或 https。
- 定时备份没执行:
crontab -l 确认任务存在;看 /var/log/backup.log;cron 环境变量少,脚本里命令用绝对路径。
面试常问
-
讲讲你们项目的完整部署架构?
按本课架构图讲:用户 → Nginx(443,TLS、静态资源、限流)→ Spring Boot 容器 → MySQL/Redis 容器;CI/CD 走 GitHub Actions,push main 自动构建镜像、SSH 部署、健康检查;数据每天 mysqldump 备份到对象存储;watchdog 每分钟探活,异常发钉钉告警。最后补一句权衡:单机 compose 是成本与复杂度的平衡,流量增长后可以平滑演进到多机 + K8s。
-
如果让你重新设计,哪里可以做得更好?
展示成长思维的送分题。可以讲:加 Prometheus 做指标监控、加 staging 环境做发布前验证、用蓝绿部署做到零停机、Terraform 管理云资源让基础设施也代码化。
-
服务半夜挂了,告警把你叫醒,你的处理流程?
①确认影响面(是全挂还是部分功能);②快速恢复优先——先重启/回滚止血,再查根因;③根因分析看日志和监控,写复盘记录;④改进:把这次故障对应的检查项加入 checklist 或监控。
自测三问
- 不看本课,默画出你的项目部署架构图,标出每个组件的端口和数据流向。
- 服务器明天要被回收,你只有 30 分钟,按什么顺序抢救和重建?
- 你的 checklist 里哪三项是上次上线时差点漏掉的?
小结一句话
DevOps 的终极目标:让「上线」从一场提心吊胆的仪式,变成一条可重复、可回滚、可监控的标准流水线。
延伸