综合php项目,两回合制首回合如何部署?

wen PHP项目 2

两回合制 PHP 项目首回合部署方案

在两回合制部署(如灰度发布、蓝绿部署、A/B 双版本并存)中,首回合部署的核心目标是:让新版本能在不影响现有服务的前提下上线,并具备随时回滚的能力

综合php项目,两回合制首回合如何部署?

下面给出一个完整的 PHP 项目首回合部署方案。


部署模型选择

常见两回合制部署有两种形态:

模型 首回合含义 适用场景
蓝绿部署 首回合把新版本部署到"绿"环境,流量仍走"蓝" 要求零停机、可秒级回滚
灰度/金丝雀 首回合只放小比例流量到新版本 大流量、需真实流量验证

首回合的共同点

  1. 新版本部署到独立环境/路径(不覆盖线上)
  2. 数据层兼容(新旧版本能同时读写)
  3. 流量切换开关就绪但默认不切小比例切
  4. 回滚路径已准备好

首回合部署流程(以蓝绿为例)

环境隔离

/var/www/
├── blue/        # 当前线上版本 (v1)
├── green/       # 首回合要部署的新版本 (v2)
└── shared/      # 共享资源
    ├── .env
    ├── storage/    # 日志、缓存、上传
    └── sessions/

Nginx 通过软链切换:

root /var/www/current/public;

代码交付(不覆盖线上)

# 拉取新代码到 green
cd /var/www/green
git fetch origin
git checkout v2.0.0
# 复用共享资源(软链)
ln -sfn /var/www/shared/.env .env
ln -sfn /var/www/shared/storage storage
ln -sfn /var/www/shared/sessions ../../shared/sessions

依赖安装(隔离于 blue)

composer install --no-dev --optimize-autoloader --no-interaction

⚠️ 不要执行 composer update,使用 composer.lock 保证可复现。

数据层兼容处理(关键)

首回合最大风险是数据库结构变更,原则:

  • 只加不改:新增字段、新增表;不删字段、不改字段类型
  • 可空默认值:新字段必须有默认值或允许 NULL
  • 双写/双读兼容:旧代码遇到新字段无感知
// 迁移脚本示例:只做加法
Schema::table('orders', function (Blueprint $table) {
    $table->string('channel')->nullable()->after('status');
});

执行迁移时:

php artisan migrate --force   # Laravel
# 或
php bin/console doctrine:migrations:migrate --no-interaction  # Symfony

缓存/配置预热(针对 green)

php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan opcache:compile   # 若使用

注意:Laravel 的 config:cache 会写进 green 自己的 bootstrap/cache,不影响 blue。

健康检查(切换前必做)

通过内网直接访问 green,不经过线上入口:

curl -H "Host: www.example.com" http://127.0.0.1:8081/health
# 或指向 green 的本地 Nginx
curl http://green.internal/health

健康检查应包含:

  • HTTP 200
  • 关键依赖(DB/Redis/MQ)可连
  • 版本号正确
// /health 路由
Route::get('/health', function () {
    DB::connection()->getPdo();
    Redis::ping();
    return response()->json([
        'status' => 'ok',
        'version' => config('app.version'),
    ]);
});

首回合收尾:不切或小比例切

蓝绿current 软链保持不变,流量仍走 blue;等待第二回合正式切换。

# 此时保持:
# current -> /var/www/blue
# 不做任何切换

灰度:在 Nginx/SLB 层放小比例流量:

upstream backend {
    server 127.0.0.1:8080 weight=95;  # blue
    server 127.0.0.1:8081 weight=5;   # green
}

首回合部署脚本示例(可落地)

deploy.sh

#!/usr/bin/env bash
set -euo pipefail
NEW_DIR="/var/www/green"
SHARED="/var/www/shared"
REPO="git@git.example.com:app.git"
TAG="$1"
echo "==> 1. 拉取代码"
cd "$NEW_DIR"
git fetch --tags
git checkout "$TAG"
echo "==> 2. 挂载共享资源"
ln -sfn "$SHARED/.env" .env
ln -sfn "$SHARED/storage" storage
echo "==> 3. 安装依赖"
composer install --no-dev --optimize-autoloader --no-interaction
echo "==> 4. 数据库迁移(向后兼容)"
php artisan migrate --force
echo "==> 5. 预热缓存"
php artisan config:cache
php artisan route:cache
echo "==> 6. 健康检查"
for i in {1..5}; do
    if curl -sf http://green.internal/health >/dev/null; then
        echo "健康检查通过"
        break
    fi
    sleep 2
    [ "$i" = "5" ] && { echo "健康检查失败"; exit 1; }
done
echo "==> 首回合完成:green 就绪,等待第二回合切换"

首回合必须注意的坑

说明
Session 共享 若用文件 Session,务必走 shared 目录或改 Redis,否则切换时用户掉线
上传目录 必须共享,不能跟着代码版本走
日志 新旧版本日志分离,便于排查,但要有统一聚合
Cron / Queue 首回合只跑旧版本的 worker,避免新任务对旧代码不可读
迁移不可逆 首回合迁移只能"加",为了第二回合能回滚,禁止 dropColumn
OPcache 若开启,务必检查 green 独立 OPcache,防止缓存串版本
.env 差异 新版本新配置项要有默认值或提前写入 shared/.env
CDN / 静态资源 带 hash 文件名,避免新旧资源冲突

首回合结束的"验收清单"

  • [ ] green 代码部署完成,软链共享资源正常
  • [ ] composer 依赖安装完成,无版本漂移
  • [ ] 数据库迁移已执行,旧版本仍能正常运行
  • [ ] 缓存已预热
  • [ ] 内网健康检查通过
  • [ ] 日志可正常写入
  • [ ] Cron/Queue 仍指向 blue
  • [ ] 流量仍集中在 blue(或仅 5% 在 green)
  • [ ] 回滚脚本已准备(只需切软链或权重)
  • [ ] 监控面板已加入 green 维度

总结一句话

首回合 = "部署但不上量":把新版本完整地放到旁路环境,验证通过、数据兼容,流量不动;第二回合才做原子切换或逐步放量,回滚能力在首回合就必须具备,否则两回合制就失去了意义。

如果你能说明具体场景(Laravel/Symfony/自研?K8s 还是裸机?灰度还是蓝绿?),我可以把方案细化到可直接执行的脚本。

抱歉,评论功能暂时关闭!