PHP 怎么PHP 蓝绿

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 蓝绿

  1. 什么是蓝绿部署
  2. PHP蓝绿部署实现方案
  3. 最佳实践建议

我来详细解释一下PHP的蓝绿部署策略。

什么是蓝绿部署

蓝绿部署是一种零停机部署策略,通过维护两套完全相同但独立的环境(蓝色和绿色)来实现。

PHP蓝绿部署实现方案

基本架构

用户请求 → 负载均衡器 → 蓝环境 或 绿环境

具体实现方式

使用Nginx + 符号链接

# nginx配置示例
upstream php_backend {
    # 使用unix socket更高效
    server unix:/var/run/php/php-fpm-blue.sock;
    # server unix:/var/run/php/php-fpm-green.sock;
}
server {
    listen 80;
    server_name example.com;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        fastcgi_pass php_backend;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

使用负载均衡器(HAProxy)

# haproxy配置
frontend php_frontend
    bind *:80
    default_backend php_blue
backend php_blue
    server php-blue-1 192.168.1.101:80 check
    server php-blue-2 192.168.1.102:80 check
backend php_green
    server php-green-1 192.168.1.201:80 check
    server php-green-2 192.168.1.202:80 check

PHP部署脚本示例

<?php
// blue-green-deploy.php
class BlueGreenDeployment {
    private $bluePath = '/var/www/blue';
    private $greenPath = '/var/www/green';
    private $activeSymlink = '/var/www/current';
    /**
     * 部署到非活动环境
     */
    public function deployToInactive() {
        $inactiveEnv = $this->getInactiveEnvironment();
        $deployPath = ($inactiveEnv === 'blue') ? $this->bluePath : $this->greenPath;
        echo "Deploying to {$inactiveEnv} environment...\n";
        // 1. 拉取最新代码
        $this->pullLatestCode($deployPath);
        // 2. 安装依赖
        $this->installDependencies($deployPath);
        // 3. 运行数据库迁移
        $this->runMigrations($deployPath);
        // 4. 执行测试
        if ($this->runTests($deployPath)) {
            echo "Tests passed. Switching traffic...\n";
            $this->switchTraffic();
        } else {
            echo "Tests failed. Aborting deployment.\n";
        }
    }
    /**
     * 获取当前非活动环境
     */
    private function getInactiveEnvironment() {
        $current = readlink($this->activeSymlink);
        return (strpos($current, 'blue') !== false) ? 'green' : 'blue';
    }
    /**
     * 切换流量到新的环境
     */
    private function switchTraffic() {
        $newEnv = $this->getInactiveEnvironment();
        $newPath = ($newEnv === 'blue') ? $this->bluePath : $this->greenPath;
        // 更新符号链接
        unlink($this->activeSymlink);
        symlink($newPath, $this->activeSymlink);
        echo "Traffic switched to {$newEnv} environment.\n";
        // 等待一段时间确保所有请求完成
        sleep(10);
        // 可以清理旧环境
        $this->cleanOldEnvironment();
    }
    private function pullLatestCode($path) {
        chdir($path);
        exec('git pull origin master', $output, $returnCode);
        return $returnCode === 0;
    }
    private function installDependencies($path) {
        chdir($path);
        exec('composer install --no-dev --optimize-autoloader', $output, $returnCode);
        return $returnCode === 0;
    }
    private function runMigrations($path) {
        chdir($path);
        exec('php artisan migrate --force', $output, $returnCode);
        return $returnCode === 0;
    }
    private function runTests($path) {
        chdir($path);
        exec('php vendor/bin/phpunit', $output, $returnCode);
        return $returnCode === 0;
    }
    private function cleanOldEnvironment() {
        $oldEnv = $this->getInactiveEnvironment();
        echo "Old environment ({$oldEnv}) can be cleaned up.\n";
    }
}
// 使用示例
$deployer = new BlueGreenDeployment();
$deployer->deployToInactive();

部署流程

#!/bin/bash
# deploy.sh
# 1. 确定当前活动环境
CURRENT=$(readlink /var/www/current)
if [[ $CURRENT == *"blue"* ]]; then
    TARGET="green"
    TARGET_PATH="/var/www/green"
else
    TARGET="blue"
    TARGET_PATH="/var/www/blue"
fi
echo "Deploying to $TARGET environment..."
# 2. 部署代码
cd $TARGET_PATH
git pull origin main
composer install --no-dev --optimize-autoloader
# 3. 运行迁移
php artisan migrate --force
# 4. 清除缓存
php artisan optimize
# 5. 切换流量
ln -sfn $TARGET_PATH /var/www/current
echo "Traffic switched to $TARGET environment"
# 6. 重启PHP-FPM
sudo systemctl reload php8.1-fpm
# 7. 验证部署
curl -I http://localhost/health-check

Docker实现蓝绿部署

# docker-compose.yml
version: '3.8'
services:
  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
    ports:
      - "80:80"
    depends_on:
      - php-blue
      - php-green
  php-blue:
    build: ./php
    volumes:
      - /var/www/blue:/var/www/html
    environment:
      - APP_ENV=production
      - APP_COLOR=blue
  php-green:
    build: ./php
    volumes:
      - /var/www/green:/var/www/html
    environment:
      - APP_ENV=production
      - APP_COLOR=green

健康检查端点

<?php
// health.php - 放在应用根目录
header('Content-Type: application/json');
$healthData = [
    'status' => 'healthy',
    'environment' => getenv('APP_COLOR') ?: 'unknown',
    'timestamp' => date('Y-m-d H:i:s'),
    'php_version' => phpversion(),
    'db_connection' => checkDatabaseConnection(),
    'cache_status' => checkCache()
];
echo json_encode($healthData);
function checkDatabaseConnection() {
    try {
        // 数据库连接检查
        return true;
    } catch (\Exception $e) {
        return false;
    }
}
function checkCache() {
    // Redis/Memcached检查
    return true;
}

最佳实践建议

  1. 数据库兼容性:确保新旧两个版本的应用能兼容同一数据库结构
  2. 会话管理:使用外部会话存储(Redis/数据库)而非文件存储
  3. 缓存清空:切换前清空OpCache、应用缓存
  4. 监控告警:部署后密切监控错误率和响应时间
  5. 回滚策略:保留上一个版本的部署,便于快速回滚
  6. 渐进切换:可以先切换10%的流量,观察无问题后再完全切换

蓝绿部署能有效减少部署风险,但需要合理的资源规划和配置管理。

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