本文目录导读:

- 核心原理:两套完全相同的环境
- 方案一:基于文件系统 + Nginx(最经典、开源)
- 方案二:基于 Docker 容器 + 反向代理(如 Nginx/Haproxy)
- 方案三:基于云原生负载均衡器(AWS / 阿里云)
- 必须解决的关键挑战:数据库兼容性
- 总结:针对不同 PHP 项目的建议
- 实施中的注意事项(黄金法则)
在 PHP 项目中实现蓝绿部署,核心目标是零停机时间(Zero Downtime) 和快速回滚(Instant Rollback)。
由于 PHP 本身是一种无状态、请求-响应模式的脚本语言(通常配合 PHP-FPM 或 Mod-PHP),它不像 Java 或 Node.js 那样有长期运行的应用进程,PHP 的蓝绿部署主要依赖于负载均衡器和文件系统/容器的切换。
以下是几种在 PHP 项目中实现蓝绿部署的详细方案:
核心原理:两套完全相同的环境
- 蓝环境(Blue): 当前正在运行的生产环境(旧版本)。
- 绿环境(Green): 准备上线的新版本环境。
- 切换点: 负载均衡器(Nginx、HAProxy、云服务商 LB)改变流量指向。
基于文件系统 + Nginx(最经典、开源)
这是成本最低、最直接的方式,适合中小型项目,或未容器化但使用 PHP 传统托管架构的项目。
目录结构
/var/www/
├── blue/ # 当前版本
│ └── current/ -> /var/www/releases/v1.0.0/
├── green/ # 新版本
│ └── current/ -> /var/www/releases/v2.0.0/
└── releases/ # 历史版本存档
├── v1.0.0/
└── v2.0.0/
实施步骤
-
准备工作
- 服务器上准备好 Nginx + PHP-FPM。
- 创建两个独立的站点根目录:
/var/www/blue/和/var/www/green/。 - 它们各自指向实际的代码发布目录。
-
部署新版本(切换到 Green)
- 将新代码部署到
/var/www/green/目录(或者通过符号链接指向新版本文件夹)。 - 关键操作: 运行数据库迁移(如果需兼容新旧两个版本的数据库结构,见下文“数据库兼容性”)。
- 热身(可选): 对 Green 环境发几个请求,让 PHP OpCache 预热。
- 将新代码部署到
-
切换流量
- 修改 Nginx 配置,将
root或try_files指向green目录:# 原来是:root /var/www/blue/current/public; root /var/www/green/current/public;
- 优雅重载 Nginx:
nginx -s reload(通常对用户无影响)。
- 修改 Nginx 配置,将
-
验证与回滚
- 验证 Green 环境运行正常。
- 回滚: 只需将 Nginx 配置改回
blue,重载即可,秒级回滚。
优点: 无需 Docker,架构简单。 缺点: 服务器 IP 固定,回滚时需再次操作 Nginx;对环境一致性要求较高(需确保服务器配置相同)。
基于 Docker 容器 + 反向代理(如 Nginx/Haproxy)
这是当前最流行的云原生方案,尤其适用于微服务或复杂依赖的项目。
架构图(简略)
用户请求
│
▼
(负载均衡器 / LB)
│
├── 指向: blue.v2.example.com (端口 8081) ──> Docker 容器 A (旧代码)
│
└── 指向: green.v3.example.com (端口 8082) ──> Docker 容器 B (新代码)
实施步骤
-
定义两套 Docker Compose 环境
docker-compose.blue.yml:启动蓝环境(旧镜像)。docker-compose.green.yml:启动绿环境(新镜像)。- 或者使用 docker-compose 的 scale + 独立 service命名 (如
app_blue,app_green)。
-
部署流程(自动化脚本或 CI/CD 执行)
# 1. 拉取新镜像并启动 Green 容器(不关闭 Blue) docker-compose -f docker-compose.green.yml up -d # 2. 等待 Green 健康检查通过 while ! curl -f http://localhost:8082/health; do sleep 2; done # 3. 切换负载均衡器(Nginx upstream) # 修改 Nginx 配置,将 upstream 从 blue 指向 green # 或 修改云 LB 后端指向 green 容器的端口/IP # 4. 停掉 Blue 容器 docker-compose -f docker-compose.blue.yml down
-
Nginx 配置示例(动态 Upstream)
upstream php_app { # server blue_app:8080; # 旧 server green_app:8080; # 新 } server { location / { proxy_pass http://php_app; } }
优点: 环境完全隔离,资源利用率高(可共用数据库,但建议容器间网络隔离);易于与 Kubernetes 集成。 缺点: 需要 Docker 和容器编排知识;如果项目不大,引入 Docker 会增加复杂性。
基于云原生负载均衡器(AWS / 阿里云)
如果使用云服务,可以利用其流量管理能力,实现 “零配置” 的蓝绿部署。
AWS 示例(类似阿里云 SLB)
-
准备工作
- 建立两个 Auto Scaling Group (ASG) 或 EC2 实例组。
ASG-Blue:运行旧代码,挂载到 ALB 目标组。ASG-Green:运行新代码,未挂载到 ALB。
-
部署流程
- 准备新的 AMI(镜像)或用户数据脚本,部署新代码。
- 启动一个 Green 实例(属于 ASG-Green)。
- 手动将 Green 实例注册到 ALB 的目标组中(但 ALB 的监听规则暂时不转发)。
- 健康检查通过后,修改 ALB 的监听规则:权重
Green:100,Blue:0。 - 验证流量全部切换。
- 销毁 / 停止 Blue 实例。
优点: 无需管理服务器细节;自动处理健康检查和流量切换。 缺点: 依赖特定云厂商 API;成本可能略高(保持两套实例同时运行)。
必须解决的关键挑战:数据库兼容性
蓝绿部署最大的难点是数据层,如果新代码修改了数据库表结构,旧代码可能无法运行。
解决方案:
- 向后兼容的数据库迁移:
- 只允许 增加字段(ADD COLUMN),不允许 删除或重命名旧字段。
- 如果必须改字段名:先新增字段,部署新代码(两套代码都可读写旧字段),下一轮部署时再删除旧字段。
- 如果必须删除字段:先发布不依赖该字段的新代码(蓝绿切换),再单独运行删除迁移。
- 分支数据库方案(不推荐但可用):
给 Blue 和 Green 各配一个独立数据库,这会导致数据不同步,通常只用于短期灰度测试,不适合生产环境长时间保持。
常见做法: 采用“向前兼容”的迁移策略,让旧代码(蓝)在绿环境运行期间不会“炸掉”,切换完成后,旧代码不会再被访问,此时再执行最终的清理迁移。
针对不同 PHP 项目的建议
| 项目类型 | 推荐方案 | 原因 |
|---|---|---|
| 小型 PHP 项目 / 传统 LAMP | 文件系统 + Nginx | 简单,无额外基础设施成本,适合单机或少量服务器。 |
| 中型项目 / 使用 Docker | Docker + Nginx/Haproxy | 环境隔离好,部署灵活,易于配合 CI/CD(如 GitLab CI)。 |
| 大型项目 / 高并发 | 云原生 LB + 自动伸缩 | 基础设施完善,可以精细控制流量(权重、灰度),配合 K8s。 |
| 使用 PHP 框架(Laravel/Symfony) | 方案一或二 | 注意处理好 .env 文件和环境变量(缓存、队列、日志路径)的独立。 |
实施中的注意事项(黄金法则)
- Session 问题: PHP 使用文件 Session 时,切换前后实例 Session 会丢失,解决方案:使用 Redis/Memcached 存储 Session,并配置为同一组 Redis 实例(蓝绿共用)。
- 文件上传 / 静态资源: 确保上传的文件(如用户头像)存储在共享外部存储(如 NFS、S3、OSS),而不是本地磁盘,否则切换后新实例看不到旧文件。
- OpCache 预热: PHP 的 OpCache 需要缓存文件,切换后第一个请求可能会慢,解决方案:部署脚本中对 Green 环境先进行 HTTP 请求(如
wget -O /dev/null http://green_server/health)。 - 长连接 / WebSocket: 蓝绿切换会导致 WebSocket 断开,需要配合客户端重连逻辑,或使用类似 Redis Pub/Sub 的消息桥接。
- 测试验证: 切换后立即运行一组自动化测试(Smoke Test),确保环境健康。
一句话总结: 蓝绿部署的核心是准备一套完整的新环境(绿),然后通过修改负载均衡配置瞬间切换流量,最终清理旧环境(蓝),PHP 项目因其无状态特性,该模式非常适合,只需注意处理数据库兼容性和共享文件存储即可。