一、"我的电脑上明明能跑啊"
自从上了测试,团队发现了一个经典问题:代码在小陈电脑上测试全绿,但部署到服务器就崩。
小陈:"我的电脑上明明能跑啊!"
老周:"那为什么服务器上跑不了?"
排查了半天:小陈电脑上 Python 是 3.12,服务器是 3.10;小陈电脑上有某个依赖的缓存,服务器上全新环境没有;小陈的数据库是本地 SQLite,服务器是 MySQL……
"问题出在'构建'这个环节。"老周说,"构建(Build),就是把源代码变成'能运行的东西'的过程——装依赖、编译、打包、配置。'我电脑上能跑',只说明'我的环境能跑',不代表'任何环境都能跑'。构建必须标准化、可重复:在谁电脑上构建、在哪儿构建,结果必须一样。"
二、第五层:持续集成(CI)——让合并的代码"当场验货"
2.1 从"手动验货"到"自动验货"
"以前我们的流程是:谁改完代码 → 手动在本地跑测试 → 觉得没问题 → 合并。"老周说,"问题有两个:手动跑测试靠自觉,可能忘跑;本地环境五花八门,跑出来不算数。"
"持续集成(CI, Continuous Integration) 解决的就是这个:每次代码提交(push)到共享仓库,服务器自动帮你做一遍'验货'——拉最新代码、装依赖、跑构建、跑全部测试。 验货不过,当场报警,不许合并。"
# GitHub Actions(CI 配置示例):每次 push 自动跑
name: CI 验货
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # 拉代码
- uses: actions/setup-python@v5 # 装 Python
with: { python-version: "3.12" }
- run: pip install -r requirements.txt # 装依赖
- run: pytest tests/ -q # 跑全部测试
- run: ruff check . # 静态检查
"你看,构建、测试、检查,全部自动化,在统一环境里跑。 谁提交了烂代码,CI 当场亮红灯。'我电脑上能跑'从此失效——服务器上跑不过,就是不行。"
2.2 冒烟测试:上线前的"快速体检"
"CI 里除了全量测试,还可以加一道冒烟测试(Smoke Test)——不测细节,只测'最核心的流程能不能跑通':系统能启动吗?首页能打开吗?下单能走通吗?"
"像火灾后检查房子,不用全屋检查,先看承重墙有没有塌。冒烟测试就是'上线前的快速体检',几分钟出结果。"
三、第六层:持续部署与运维——让上线不再是"鬼门关"
3.1 周四发布日的恐怖故事
"你们知道为什么我最怕周四吗?"老周问。
小陈:"因为……周五大家就跑了?"
"对了一半。"老周说,"以前我们的发布流程是:周四下午手动打包 → 手动传到服务器 → 手动重启 → 祈祷。每次上线,全团队屏息凝神,像拆炸弹。 出了事,谁也不知道哪一步出错了,只能现场改、现场试、现场哭。"
"这种'发布靠运气'的状态,必须终结。方法就是 CD(Continuous Delivery / Deployment,持续交付/持续部署)——把'发布'也变成自动化流水线。"
3.2 发布流水线:从提交到上线的"传送带"
老周画出完整的流水线:
开发者提交代码
│
▼
① CI 自动构建 + 测试(全量) ← 红灯:打回,不许合并
│ 绿灯
▼
② 自动部署到"测试环境" ← 开发/测试在这里验收
│ 验收通过
▼
③ 自动部署到"预发布环境" ← 跑冒烟测试,模拟生产
│ 冒烟通过
▼
④ 手动确认(一键)→ 部署到"生产环境"
│
▼
⑤ 自动跑生产冒烟测试 + 监控告警 ← 上线后持续盯着
"关键要点:"
- 环境分层:开发环境 → 测试环境 → 预发布环境 → 生产环境。每一层都在流水线上,代码一路"流"下去,人工干预点越少越好。
- 一键部署:生产环境部署变成"点一个按钮"(或自动触发),不再是人肉敲命令。
- 部署要可重复:同样的流水线跑 100 次,结果必须一样——这就是为什么之前强调"构建标准化"。
# CD 流水线片段:部署到测试环境
deploy-test:
needs: [test]
steps:
- run: docker build -t yunjian/shop:$GITHUB_SHA . # 构建镜像
- run: docker push yunjian/shop:$GITHUB_SHA # 推送镜像
- run: ssh test-server "docker compose up -d" # 测试环境部署
3.3 回滚:发布失败的"后悔药"
"自动化发布最大的好处之一:出问题可以一键回滚。"老周说,"部署的本质,是'把新版本切到线上'。那'切回去'就是回滚(Rollback)。"
两种回滚姿势:
1. 版本回退:把线上切回上一个稳定版本(最快,推荐)
2. 修复重发:在最新代码上修 bug,再走一遍流水线(较慢,但保留新功能)
原则:先止血(回滚恢复服务),再研究(为什么崩)。
别在线上边查边改——用户等不起。
"每次发布必须带上'怎么回滚'的方案,就像出海必须带救生艇。没有回滚方案的发布,是不允许的。"
3.4 监控与告警:别等用户发现系统挂了
"最后是最扎心的一课。"老周表情严肃,"上个月我们线上崩了一次,你猜我们多久发现的?"
小陈摇头。
"40 分钟。40 分钟后,是客服小姐姐发现'下单一直失败'才通知我们。"老周说,"没有监控的系统,就像蒙着眼开车。 必须让机器替我们'盯梢':"
监控三件套:
1. 日志(Logs) :系统运行记录,排查问题的"案发现场"
2. 指标(Metrics) :每秒请求数、错误率、响应时间、服务器 CPU/内存
3. 告警(Alerting):指标异常自动报警(微信/短信/电话)
云间书店的监控指标:
- 订单成功率 < 95% → 立即告警
- 结算页响应时间 > 3 秒 持续 5 分钟 → 告警
- 服务器 CPU > 85% 持续 10 分钟 → 告警
"有了监控,线上出问题,机器比用户先发现。这属于 SRE(Site Reliability Engineering,站点可靠性工程) 的范畴——用工程的思维保证系统稳定可靠。"
四、章末:老周的第五、六层总结
第五层:构建与集成
├── 构建标准化 → "我电脑上能跑"不算数,任何环境都能构建才算
├── 持续集成(CI) → 每次提交自动构建+测试,红灯打回
└── 冒烟测试 → 上线前快速体检核心流程
第六层:部署与运维
├── 环境分层 → 开发→测试→预发布→生产,逐级流下去
├── 一键部署 → 发布不再人肉,流水线自动化
├── 回滚 → 没有回滚方案的发布是不允许的
├── 监控告警 → 机器比用户先发现问题(日志/指标/告警)
└── SRE → 用工程思维保证系统可靠
"小陈,到这一章,我们的代码从'写完'到'上线'已经全链路自动化了。"老周说,"但是——你有没有发现,我们一直都在解决'技术'问题,还没碰过一个更头疼的?"
小陈想了想:"您是说……需求永远做不完?上线日期永远赶不上?"
"对。技术再顺,如果大家各干各的、没有节奏、排期永远被打乱,团队照样乱。 下一章,我们不讲技术了——讲'人怎么组织'。项目管理与团队协作,这才是管理这个词的本义。"