PHP 怎么蓝绿部署

wen PHP项目 2

本文目录导读:

PHP 怎么蓝绿部署

  1. 什么是蓝绿部署
  2. 基本架构
  3. 实现方案
  4. PHP 应用注意事项
  5. 健康检查实现
  6. 自动化部署工具
  7. 最佳实践

我来详细讲解 PHP 应用的蓝绿部署策略。

什么是蓝绿部署

蓝绿部署是一种零停机部署策略,通过维护两个相同的生产环境(蓝色和绿色),在版本切换时实现无缝更新。

基本架构

                    ┌─────────────┐
                    │  负载均衡器   │
                    │  (Nginx/LB) │
                    └─────┬───────┘
                          │
              ┌───────────┼───────────┐
              │           │           │
        ┌─────▼─────┐ ┌───▼─────────┐
        │  蓝色环境   │ │  绿色环境   │
        │ (当前版本) │ │ (新版本)   │
        └───────────┘ └─────────────┘

实现方案

基于 Nginx 的蓝绿部署

# nginx.conf
upstream blue_green {
    # 当前活跃环境
    server 192.168.1.10:8080;  # 蓝色环境
    # server 192.168.1.11:8080;  # 绿色环境(部署时切换)
}
server {
    listen 80;
    server_name example.com;
    location / {
        proxy_pass http://blue_green;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

切换部署脚本:

#!/bin/bash
# deploy.sh
# 切换到绿色环境
echo "Switching to Green environment..."
# 1. 更新 Nginx 配置
sed -i 's/192.168.1.10/192.168.1.11/g' /etc/nginx/nginx.conf
# 2. 测试配置
nginx -t
# 3. 重载 Nginx
nginx -s reload
# 4. 验证
curl -s http://example.com/healthcheck

基于 Docker 容器的蓝绿部署

# docker-compose.yml
version: '3.8'
services:
  app-blue:
    image: myapp:blue
    container_name: app-blue
    ports:
      - "8080:80"
    networks:
      - app-network
  app-green:
    image: myapp:green
    container_name: app-green
    ports:
      - "8081:80"
    networks:
      - app-network
networks:
  app-network:
    driver: bridge

自动化部署脚本:

#!/bin/bash
# blue-green-deploy.sh
# 获取当前活跃环境
ACTIVE_BLUE=$(docker ps --filter "name=app-blue" --format "{{.Names}}" | wc -l)
if [ "$ACTIVE_BLUE" -gt 0 ]; then
    # 当前蓝环境活跃,部署到绿环境
    echo "Deploying to Green environment..."
    # 1. 构建新版本
    docker build -t myapp:green .
    # 2. 启动绿色容器
    docker-compose up -d app-green
    # 3. 健康检查
    if curl -f http://localhost:8081/health; then
        echo "Green environment is healthy"
        # 4. 切换流量到绿色
        sed -i 's/app-blue/app-green/g' /etc/nginx/nginx.conf
        nginx -s reload
        # 5. 停止蓝色环境
        docker-compose stop app-blue
    else
        echo "Deployment failed, rolling back"
        docker-compose stop app-green
    fi
else
    # 当前绿环境活跃,部署到蓝环境
    echo "Deploying to Blue environment..."
    docker build -t myapp:blue .
    docker-compose up -d app-blue
    if curl -f http://localhost:8080/health; then
        sed -i 's/app-green/app-blue/g' /etc/nginx/nginx.conf
        nginx -s reload
        docker-compose stop app-green
    else
        docker-compose stop app-blue
    fi
fi

基于 Kubernetes 的蓝绿部署

# blue-green-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-blue
  labels:
    app: myapp
    version: blue
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: blue
  template:
    metadata:
      labels:
        app: myapp
        version: blue
    spec:
      containers:
      - name: php-app
        image: myapp:1.0.0
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-green
  labels:
    app: myapp
    version: green
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      version: green
  template:
    metadata:
      labels:
        app: myapp
        version: green
    spec:
      containers:
      - name: php-app
        image: myapp:1.1.0
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
    version: blue  # 切换时为 green
  ports:
  - port: 80
    targetPort: 80

PHP 应用注意事项

数据库兼容性

// 处理数据库迁移
class DatabaseMigration {
    public function checkCompatibility() {
        // 检查新旧版本数据库兼容性
        $currentVersion = $this->getSchemaVersion();
        if ($currentVersion < $this->targetVersion) {
            // 可以在切换前执行迁移
            $this->migrateDatabase();
        }
    }
}

会话管理

// 使用共享会话存储(如 Redis)
session_set_save_handler(
    new RedisSessionHandler($redis)
);
// 或者配置 session 存储
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://redis-server:6379');

配置文件管理

// config.php
class AppConfig {
    public static function getEnvironment() {
        // 通过环境变量识别当前环境
        return getenv('APP_ENV') ?: 'blue';
    }
    public static function getDatabaseConfig() {
        $env = self::getEnvironment();
        return [
            'blue' => [
                'host' => 'db-blue.example.com',
                'database' => 'app_blue'
            ],
            'green' => [
                'host' => 'db-green.example.com',
                'database' => 'app_green'
            ]
        ][$env];
    }
}

健康检查实现

// healthcheck.php
<?php
header('Content-Type: application/json');
$checks = [
    'database' => checkDatabase(),
    'cache' => checkCache(),
    'filesystem' => is_writable('/var/www/app')
];
foreach ($checks as $name => $passed) {
    if (!$passed) {
        http_response_code(500);
        echo json_encode(['status' => 'error', 'check' => $name]);
        exit;
    }
}
echo json_encode(['status' => 'healthy']);

自动化部署工具

使用 Ansible

# deploy.yml
---
- hosts: webservers
  tasks:
    - name: Deploy new version to inactive environment
      shell: |
        if [ -f /var/www/blue/index.php ]; then
          echo "Deploying to green"
          cp -r /tmp/release/* /var/www/green/
        else
          echo "Deploying to blue"
          cp -r /tmp/release/* /var/www/blue/
        fi
    - name: Run health check
      uri:
        url: "http://localhost/healthcheck"
        return_content: yes
      register: health_check
    - name: Switch traffic
      file:
        path: /etc/nginx/sites-enabled/myapp
        state: link
        src: /etc/nginx/sites-available/myapp-green.conf
      when: health_check.content is search('healthy')

使用 Jenkins Pipeline

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:${BUILD_NUMBER} .'
            }
        }
        stage('Deploy to Inactive') {
            steps {
                script {
                    def activeEnv = sh(script: 'curl -s https://api.example.com/active', returnStdout: true)
                    def targetEnv = activeEnv.trim() == 'blue' ? 'green' : 'blue'
                    sh "docker tag myapp:${BUILD_NUMBER} myapp:${targetEnv}"
                    sh "docker-compose up -d app-${targetEnv}"
                }
            }
        }
        stage('Switch Traffic') {
            steps {
                script {
                    def activeEnv = sh(script: 'curl -s https://api.example.com/active', returnStdout: true)
                    def targetEnv = activeEnv.trim() == 'blue' ? 'green' : 'blue'
                    sh "sed -i 's/${activeEnv}/${targetEnv}/g' /etc/nginx/nginx.conf"
                    sh 'nginx -s reload'
                }
            }
        }
    }
}

最佳实践

  1. 自动回滚机制

    • 健康检查失败时自动回滚
    • 监控响应时间和错误率
  2. 数据同步

    • 切换前确保数据库同步
    • 使用数据库复制或多主数据库
  3. 缓存清理

    • 切换时清理 OpCache
    • 刷新 CDN 缓存
  4. 监控告警

    • 实时监控两个环境
    • 设置切换时的性能指标对比
  5. 灰度发布

    • 可以结合按比例分配流量
    • 逐步增加新环境流量

蓝绿部署能显著降低发布风险,但需要确保两个环境配置完全一致,并做好数据同步机制。

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