《持续交付》读后:CI/CD不是口号,是每天都能上线的底气
写在前面
大三这年,我同时维护着好几个项目:灵山胜境AI数字人导游、销售生产ERP系统、HomeBox库存管理……每过一个迭代,最怕的就是"上线"这个动作本身。
《持续交付》(Continuous Delivery,Jez Humble & David Farley 著)这本书,让我意识到:部署不应该是一场冒险,而应该是日常工作的一部分。
一、什么是"持续交付"?
很多人把持续交付等同于"有CI流水线"。书里给了一个更严格的定义:
持续交付,是让软件随时可以安全、低风险地发布到生产环境的一种能力。
注意关键词:随时、安全、低风险。
不是"我有Jenkins在跑",而是"每次提交都能自动走到一个可发布的状态"——这才是持续交付。
二、最戳我的几个观点
1. "部署"和"发布"是两件事
这本书最让我醍醐灌顶的区分:
| 概念 | 含义 |
|---|---|
| 部署(Deploy) | 把软件放到某个环境(测试/预发/生产) |
| 发布(Release) | 让用户看到新版本 |
部署是技术动作,发布是业务决策。
这意味着:你可以频繁部署到生产环境,但通过一个开关(Feature Flag)控制用户是否看到——这就是"暗发布"(Dark Launching)。
在ERP系统的飞书机器人模块里,我把DeepSeek调用链路做了开关化:
# erp/config.py
FEATURE_DEEPSEEK_QA = os.getenv("FEATURE_DEEPSEEK_QA", "enabled")
# erp/feishu_handler.py
def handle_message(event):
if current_app.config["FEATURE_DEEPSEEK_QA"] == "enabled":
answer = call_deepseek(event["text"])
reply_feishu(event, answer)
else:
reply_feishu(event, "智能问答功能维护中,请稍后重试")
这样即使DeepSeek接口出问题,我也能秒级切回备用回复,不用回滚代码。
2. 自动化验收测试:别只测"能跑",要测"做对了"
书里强调:验收测试(Acceptance Test)验证的是"业务行为是否正确",而不只是"代码有没有报错"。
我之前写测试的习惯是:
# ❌ 以前的写法 —— 只测了"不报错"
def test_create_order():
resp = client.post("/api/orders", json={...})
assert resp.status_code == 200 # 只要不报错就算通过?
读完书之后,我改成:
# ✅ 改进后 —— 验证业务行为
def test_create_order_should_decrease_inventory():
# 前置:库存有10件
init_inventory("SKU-001", 10)
resp = client.post("/api/orders", json={
"sku": "SKU-001",
"quantity": 3
})
assert resp.status_code == 200
# 关键断言:库存真的减了吗?
assert get_inventory("SKU-001") == 7
# 关键断言:订单状态正确吗?
assert resp.json["status"] == "PENDING"
这个转变,让我的测试从"走个过场"变成了"真正替业务逻辑把关"。
3. 流水线即文档
书里有一句话我记在笔记本上:
"如果你的交付流程只在某个人脑子里,那它就是坏的。"
我把这条原则用到了ERP系统的CI流水线上。以前部署要靠嘴说:"先跑数据库迁移,再重启Node服务,最后清Redis缓存"——现在这些步骤全部写在 .github/workflows/deploy.yml 里,新人来了照着跑就行。
# .github/workflows/deploy.yml(简化版)
name: Deploy ERP
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
cd server && ./mvnw test
cd node-service && npm test
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- name: Deploy to staging
run: |
ssh deploy@erp-server "cd /opt/erp && git pull && docker compose up -d"
- name: Smoke test
run: |
curl -f http://erp-staging/api/health || exit 1
三、落地时的真实阻碍
道理都懂,落地时还是有一堆坑:
阻碍1:数据库迁移的恐惧
每次 ALTER TABLE 都让人紧张。书里给的方案是:让每次迁移都是可回滚的,并且先在生产环境的只读副本上验证。
我现在用的策略是:迁移脚本永远写成双向的:
-- V3__add_erp_order_index.sql
-- 升级
CREATE INDEX idx_order_created_at ON erp_order(created_at DESC);
-- 回滚(写在另一个文件里)
DROP INDEX idx_order_created_at ON erp_order;
阻碍2:测试环境≠生产环境
书里反复强调:如果你的测试环境和生产环境不一样,那你测了个寂寞。
我们测试环境用的是H2内存数据库,生产用的是MySQL 8.0——结果SQL方言差异导致上线翻车过两次。后来测试环境也换成了MySQL容器,虽然慢一点,但值得。
四、对我们学生的意义
有人会说:"持续交付是大厂的东西,学生项目用不上。"
我不这么看。
学生项目恰恰是最适合练持续交付的场景——因为没有历史包袱,可以从第一天就养成好习惯:
- 每次提交都触发自动化测试
main分支永远处于可部署状态- 部署步骤全部写成代码,不靠"经验"
等大四实习、校招面试的时候,你能说"我有个项目从零开始就做到了持续交付"——这比"我会Spring Boot"值钱多了。
五、总结
《持续交付》不是一本"看完就能上手"的工具书,它更像是一本软件工程世界观的重建指南。
它让我明白:
- 部署频繁 = 风险低(每次变更小,出问题好定位)
- 手动步骤 = bug的温床(能自动化的坚决不手动)
- 流水线即信心(看着绿灯亮起,是一种踏实的快乐)
如果你也在管多个项目、也在为"上线焦虑",这本书值得翻一翻。不用全看完,把自动化验收测试和流水线设计这两章先读了,就能有不少收获。
以上纯粹个人读后感,不构成技术建议。如果有不同理解,欢迎博客园评论区交流 :)

浙公网安备 33010602011771号