资讯动态

php方案 传统php应用serverless改造

发布时间:2026/8/8 12:23:06 来源:尧图企业网站定制
---一、核心障碍清单 ┌────────────────┬─────────────────────────┬──────────┐ │ 障碍 │ 原因 │ 严重程度 │ ├────────────────┼─────────────────────────┼──────────┤ │ 文件系统依赖 │ Lambda 无持久化本地磁盘 │ 高 │ ├────────────────┼─────────────────────────┼──────────┤ │ 数据库连接耗尽 │ 每次调用创建新连接 │ 高 │ ├────────────────┼─────────────────────────┼──────────┤ │ Session 失效 │ 文件型 Session 不跨实例 │ 高 │ ├────────────────┼─────────────────────────┼──────────┤ │ 长任务超时 │ Lambda 最长15分钟 │ 中 │ ├────────────────┼─────────────────────────┼──────────┤ │ Cron 任务 │ 无系统级 crontab │ 中 │ ├────────────────┼─────────────────────────┼──────────┤ │ 冷启动延迟 │ PHP 冷启动2-4s │ 中 │ ├────────────────┼─────────────────────────┼──────────┤ │ WebSocket │ 无持久连接 │ 中 │ └────────────────┴─────────────────────────┴──────────┘---二、迁移路线图渐进式非大爆炸 推荐顺序从最容易到最难 第1步 Cron 定时任务 ── 最简单改动最小 第2步 后台队列/异步任务 ── SQS 替换 第3步 文件上传 ── 迁到 S3 第4步 Session ── 迁到 Redis/DynamoDB 第5步 只读 API ── 无状态轻松迁移 第6步 写入 API ── 需 RDS Proxy 第7步 Web 页面路由 ── 最后处理依赖上面全部 绞杀者模式Strangler Fig— 生产安全 用户请求 ↓ ALB/API Gateway ↓ 路由规则:/api/v2/* → Lambda新 /* → 原有服务器旧 新旧并行逐步切流可随时回滚。 --- 三、各障碍具体解决方案 1. 本地文件系统 // ❌ 旧写法 move_uploaded_file($tmpFile, /var/www/uploads/ . $filename); file_put_contents(/var/log/app.log, $message); // ✅ 新写法 — 上传走 S3 Storage::disk(s3)-put(uploads/ . $filename, $content); // ✅ 临时文件用 /tmp不跨调用单次可用 $tmpPath /tmp/ . uniqid() . .jpg; // 处理完立即上传 S3然后删除 unlink($tmpPath); // ✅ 日志走 CloudWatch直接 error_log 即可 error_log(json_encode([level info, msg $message])); 预签名 URL推荐— 让浏览器直传 S3Lambda 不经手文件流 $url Storage::disk(s3)-temporaryUploadUrl( uploads/ . $filename, now()-addMinutes(10) ); // 返回给前端前端直接 PUT 到 S3 return response()-json([upload_url $url]); --- 2. 数据库连接耗尽 问题100 个并发 Lambda 100 个新 DB 连接 → 超出 RDS 上限 三层防护 // 层1: 连接复用Lambda 热启动时重用连接 // bootstrap/app.php 或 config/database.php 外部静态连接 // 层2: config/database.php — 减小连接池 mysql [ options [ PDO::ATTR_PERSISTENT true, // 持久连接 ], pool [ min 1, max 5, // 单 Lambda 实例最多 5 连接 ], ], // 层3: 连接目标改为 RDS Proxy DB_HOSTmy-proxy.proxy-xxx.us-east-1.rds.amazonaws.com vapor.yml 开启 RDS Proxy # vapor.yml environments: production: database: my-rds-instance database-proxy: true # 一行搞定 --- 3. Session 迁移 // ❌ 旧文件型 Session跨实例失效 SESSION_DRIVERfile // ✅ 新Redis SESSION_DRIVERredis REDIS_HOSTmy-elasticache.xxx.cache.amazonaws.com // ✅ 更好数据库型无需额外基础设施 SESSION_DRIVERdatabase php artisan session:table php artisan migrate // ✅ 最佳API无状态 JWT彻底消灭 Session // 用 laravel/sanctum token 替代 session --- 4. 定时任务Cron // ❌ 旧服务器 crontab // * * * * * php /var/www/artisan schedule:run // ✅ 新EventBridge Lambda vapor.yml 配置 environments: production: scheduler: true # Vapor 自动创建 EventBridge 规则 每分钟触发 Laravel 调度器App\Console\Kernel 正常写 // app/Console/Kernel.php — 无需改动 protected function schedule(Schedule $schedule) { $schedule-command(reports:daily)-dailyAt(08:00); $schedule-command(cache:clear)-hourly(); } --- 5. 后台队列/异步任务 // ❌ 旧本地 Redis Horizon worker 常驻进程 // ✅ 新SQS — Serverless 原生方案 QUEUE_CONNECTIONsqs SQS_PREFIXhttps://sqs.us-east-1.amazonaws.com/xxx SQS_QUEUEdefault // 代码无需改动dispatch() 照常用 ProcessOrder::dispatch($order)-onQueue(orders); vapor.yml 配置队列 worker environments: production: queues: - orders # SQS 队列名 - emails --- 6. 长任务超过 15 分钟 选项A拆分成链式小任务Step Functions 编排 选项BSQS 分批处理每批 14 分钟 选项CECS Fargate 处理真正的长任务 // 批处理模式每次处理一小块完成后重新入队 class ProcessLargeExport implements ShouldQueue { public function handle() { $batch Item::where(status, pending) -limit(500) // 每次 500 条 -get(); // 处理这 500 条... if (Item::where(status, pending)-exists()) { // 还有数据重新入队 ProcessLargeExport::dispatch(); } } } --- 7. 冷启动优化 # 预编译路由和配置 php artisan config:cache php artisan route:cache php artisan view:cache php artisan event:cache // composer.json — 排除开发依赖减小包体积 { scripts: { vapor:deploy: composer install --no-dev --optimize-autoloader } } # vapor.yml — 配置 Provisioned Concurrency预热实例消灭冷启动 environments: production: concurrency: 5 # 常驻 5 个热实例 --- 四、Bref vs Laravel Vapor 选择 ┌──────────────┬───────────────────────┬───────────────────────┐ │ │ Bref │ Laravel Vapor │ ├──────────────┼───────────────────────┼───────────────────────┤ │ 适用框架 │ 任意 PHP │ 仅 Laravel │ ├──────────────┼───────────────────────┼───────────────────────┤ │ 费用 │ 仅 AWS 费用 │ $12-50/月 AWS │ ├──────────────┼───────────────────────┼───────────────────────┤ │ 配置复杂度 │ 较高YAML 手写 │ 低Dashboard 操作 │ ├──────────────┼───────────────────────┼───────────────────────┤ │ 自定义灵活性 │ 最高 │ 中等 │ ├──────────────┼───────────────────────┼───────────────────────┤ │ 内置队列支持 │ 手动配 SQS │ 一键开启 │ ├──────────────┼───────────────────────┼───────────────────────┤ │ 适合场景 │ 多框架混合 / 重度定制 │ 纯 Laravel / 快速上线 │ └──────────────┴───────────────────────┴───────────────────────┘ --- 五、本地测试 Serverless 环境 # 方案1Laravel Sail LocalStack最简单 docker run -d -p 4566:4566 \ -e SERVICESs3,sqs,dynamodb \ localstack/localstack # .env.local AWS_ENDPOINThttp://localhost:4566 AWS_ACCESS_KEY_IDtest AWS_SECRET_ACCESS_KEYtest # 方案2Bref 本地运行 ./vendor/bin/bref local # 方案3SAM CLI 完整模拟 sam local start-api --docker-network host --- 六、迁移前检查清单 改造前 □ 梳理所有文件读写点 □ 统计 DB 最大并发连接数 □ 列出所有 cron 任务 □ 确认第三方库的 Lambda 兼容性 □ 评估估算 AWS 成本 改造中 □ 开启 RDS Proxy □ Session 切换到 Redis/DB □ 上传迁移到 S3 □ Cron 迁移到 EventBridge □ 队列迁移到 SQS □ 用 Strangler Fig 灰度上线 改造后 □ CloudWatch 告警配置 □ Sentry 错误监控接入 □ 冷启动时间监控 □ 数据库连接数监控 □ 成本趋势追踪 --- 核心原则改造不是重写是逐步替换基础设施依赖。从无状态的边缘任务cron、队列开始最后才动核心 Web 路由每步可独立验证、回滚。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价