3、蓝绿部署实战:蓝绿部署架构、DNS切换与负载均衡器配置、数据库兼容性问题
3.1 蓝绿部署的核心思想
蓝绿部署,说白了就是准备两套完全一样的环境。
一套叫「蓝」,是当前在线的生产环境。
另一套叫「绿」,是你要发布的新版本环境。
两套环境同时运行,但只有一套对外提供服务。
我刚开始接触这个模式时,觉得有点浪费资源。但经历过一次线上事故后,我彻底改观了。那次回滚花了40分钟,用户流失惨重。如果当时用了蓝绿部署,切换就是几秒钟的事。
蓝绿部署的核心优势就两个:
- 快速切换:发现问题,一秒切回旧版本
- 零 downtime:用户几乎感知不到发布过程
关键点:蓝绿部署不是「逐步切换」,而是「瞬间切换」。这是它和金丝雀发布的本质区别。
3.2 蓝绿部署架构设计
一个标准的蓝绿部署架构,通常包含这几层:
| 层级 | 组件 | 说明 |
|---|---|---|
| 流量入口 | DNS / CDN | 负责域名解析,指向当前活跃环境 |
| 负载均衡 | Nginx / HAProxy / ALB | 分发流量到后端服务集群 |
| 应用层 | 蓝集群 / 绿集群 | 两套完全隔离的应用实例 |
| 数据层 | 数据库 / 缓存 | 需要处理兼容性问题 |
我个人习惯把蓝绿环境部署在不同的物理机群或 Kubernetes 命名空间里。这样能真正做到「物理隔离」,避免互相影响。
举个例子,我在阿里云上做过一个方案:
# 蓝环境(当前在线)
blue-cluster:
- 10.0.1.10:8080 (app-1)
- 10.0.1.11:8080 (app-2)
- 10.0.1.12:8080 (app-3)
# 绿环境(新版本)
green-cluster:
- 10.0.2.10:8080 (app-1)
- 10.0.2.11:8080 (app-2)
- 10.0.2.12:8080 (app-3)
两套环境独立部署,互不干扰。发布时,先在绿环境部署新版本,验证通过后,把流量切过去。
3.3 DNS切换:最粗暴也最有效
DNS切换是蓝绿部署里最简单的方式。你只需要修改域名解析,把流量指向新环境。
但这里有个坑——DNS缓存。
我曾经遇到过一个问题:DNS切换后,过了半小时还有用户访问旧环境。排查发现,运营商 DNS 缓存 TTL 设成了 1800 秒。
避坑指南:DNS切换前,一定要把 TTL 值调低。我一般提前 24 小时把 TTL 从 600 秒降到 60 秒。等切换完成稳定后,再调回正常值。
DNS切换的步骤大致如下:
- 提前降低 TTL(比如 60 秒)
- 在绿环境部署新版本,完成验证
- 修改 DNS 记录,指向绿环境 IP
- 等待 DNS 生效(通常几分钟)
- 监控流量和错误率
- 确认稳定后,保留蓝环境作为回滚备用
说白了,DNS切换适合「不要求秒级切换」的场景。如果你需要更快的切换速度,那就得上负载均衡器了。
3.4 负载均衡器配置实战
用负载均衡器做蓝绿切换,比 DNS 快得多。你只需要修改 upstream 配置,把流量从蓝集群切到绿集群。
我拿 Nginx 举个例子:
# 定义两个 upstream
upstream blue-cluster {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
server 10.0.1.12:8080;
}
upstream green-cluster {
server 10.0.2.10:8080;
server 10.0.2.11:8080;
server 10.0.2.12:8080;
}
# 当前指向蓝环境
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://blue-cluster;
}
}
切换时,只需要把 proxy_pass 从 blue-cluster 改成 green-cluster,然后 reload Nginx:
nginx -s reload
整个过程不到 1 秒。用户完全无感知。
小技巧:我习惯在 Nginx 里加一个健康检查。如果绿环境有问题,Nginx 会自动切回蓝环境。这样即使人不在电脑前,也能自动回滚。
用 HAProxy 也是类似的思路:
backend app-backend
option httpchk GET /health
server blue-1 10.0.1.10:8080 check weight 100
server blue-2 10.0.1.11:8080 check weight 100
server green-1 10.0.2.10:8080 check weight 0
server green-2 10.0.2.11:8080 check weight 0
切换时,把蓝环境的 weight 改成 0,绿环境的 weight 改成 100。然后 reload 配置。
你想想看,这种方式比 DNS 切换快多了吧?
3.5 数据库兼容性问题:最容易被忽视的坑
嗯,这里要注意。蓝绿部署最大的坑,不在应用层,而在数据库层。
为什么?因为数据库是「有状态」的。两套应用可以同时跑,但数据库不能同时跑两个版本。
我遇到过最典型的问题是这样的:
- 新版本改了数据库表结构(加了字段)
- 蓝环境还在用旧版本,不识别新字段
- 绿环境写入新字段后,蓝环境读取报错
说白了,数据库的兼容性问题,核心就一句话:新老版本必须能同时读写同一份数据。
怎么解决?我总结了几个实战经验:
方案一:向后兼容的数据库变更
所有数据库变更,必须做到「向前兼容」。什么意思?
- 只加字段,不改字段
- 只加表,不改表
- 新字段要有默认值
- 不要删除旧字段
举个例子:
-- 错误做法:直接删除旧字段
ALTER TABLE users DROP COLUMN old_field;
-- 正确做法:先加新字段,等所有版本都迁移后再删除
ALTER TABLE users ADD COLUMN new_field VARCHAR(255) DEFAULT '';
方案二:读写分离 + 数据同步
如果变更实在太大,可以考虑读写分离:
- 蓝环境读写主库
- 绿环境读写从库(或影子库)
- 通过数据同步工具(如 Canal、Debezium)把数据从主库同步到从库
这个方案比较复杂,我一般只在「大版本升级」时才用。
方案三:双写 + 灰度切换
新老版本同时写入数据库,但只从一个版本读取。等数据一致后,再切换读取源。
重要提醒:数据库兼容性问题,一定要在「发布前」就规划好。我见过太多团队,应用层切过去了,数据库却炸了。结果回滚都来不及。
3.6 蓝绿部署的完整流程
最后,我总结一下蓝绿部署的完整流程:
- 准备阶段:搭建蓝绿两套环境,确保配置一致
- 部署阶段:在绿环境部署新版本,运行验证测试
- 切换阶段:通过 DNS 或负载均衡器,把流量切到绿环境
- 观察阶段:监控错误率、延迟、数据库状态,持续 15-30 分钟
- 清理阶段:确认稳定后,保留蓝环境作为回滚备用
如果发现问题,直接切回蓝环境。整个过程不超过 10 秒。
我个人觉得,蓝绿部署是「性价比最高」的发布策略。它不像金丝雀发布那么复杂,也不像滚动发布那么慢。只要处理好数据库兼容性问题,几乎适用于所有场景。
好了,这一章就到这里。下一章我们聊聊「金丝雀发布」的实战细节,那个更有意思。