传统 Laravel 零改动迁移到 FrankenPHP 完整流程先把最重要的一句话说在前面免得你迁移到一半发现被坑 ▎ 「零改动」只在「经典模式」下成立。 经典模式把 FrankenPHP 当成一个更快的 NginxPHP-FPM 替代品你的 Laravel ▎ 代码一行都不用动。 ▎ ▎ 而「Worker 模式」性能翻几倍那个不是零改动——它需要装laravel/octane ▎ 这个官方包并且你的代码得满足「无状态」要求第10章讲过的那些泄漏陷阱。 所以这篇分两段走先零改动跑起来经典模式再可选地榨性能worker 模式。两条路我都给完整流程。---第一部分真·零改动迁移经典模式 步骤0迁移前盘点你现在的架构 传统 Laravel 生产环境通常长这样 浏览器 →Nginx收 HTTP、发静态文件、反代 →PHP-FPM跑 PHP通过 FastCGI 协议 →public/index.php →Laravel 涉及的配置文件-nginx.conf/sites-available/xxxNginx 站点配置-php-fpm.conf/www.confFPM 进程池配置-php.ini FrankenPHP 把 NginxPHP-FPM 两个东西合并成一个进程所以上面这套全部不再需要换成一个 Caddyfile或者干脆零配置。 步骤1装 FrankenPHP FrankenPHP 官方发布的是单个静态二进制第12章讲的静态链接 libphp 那条路的成品里面已经内置了 PHP 解释器和常用扩展你机器上甚至不需要装 PHP。 方式 A直接下二进制最省事#Linux x86_64curl https://frankenphp.dev/install.sh | shsudo mv frankenphp/usr/local/bin/# 验证里面这个 PHP 是什么版本、带哪些扩展 frankenphp php-cli-v frankenphp php-cli-m # 列出内置扩展先确认你 Laravel 要的扩展都在 方式 BDocker生产推荐环境最干净#Dockerfile ——这是迁移 Laravel 的标准官方镜像FROM dunglas/frankenphp:latest # 装 Laravel 常用的 PHP 扩展官方镜像带了 install-php-extensions 工具 RUN install-php-extensions \ pdo_mysql \ redis \ intl \ gd \ zip \ bcmath \ opcache \ pcntl # 把你的 Laravel 项目拷进镜像默认的网站根目录 COPY./app WORKDIR/app # 装依赖生产参数 RUN composer install--no-dev--optimize-autoloader ▎ 关键检查点迁移前一定先用 frankenphp php-cli-m 或 install-php-extensions 把你 composer.json 里 ext-*▎ 要求的扩展全配齐。Laravel ▎ 常见依赖pdo_mysql/pdo_pgsql、mbstring、openssl、tokenizer、xml、ctype、json、bcmath、fileinfo、redis如果用 ▎ Redis、intl、gd/imagick如果处理图片、pcntl如果用队列--timeout。少装扩展是迁移最常见的翻车点。 步骤2让 FrankenPHP 指向 Laravel 的入口 Laravel 的 HTTP 入口永远是 public/index.php所有请求都被 rewrite 到它这就是 Laravel 的「前端控制器」模式。FrankenPHP 内置了对这个模式的支持一个命令零配置就能跑 # 进到 Laravel 项目根目录 cd/path/to/your-laravel # 一行启动--root 指向 public 目录 frankenphp php-server--root public/就这一行。它会-在:443带自动 HTTPS或开发时:80起一个服务器-自动把所有请求按 Laravel 的规则 rewrite 到 public/index.php-静态文件public/下的 css/js/图片直接由服务器高速返回不走 PHP 打开浏览器访问你的 Laravel 原封不动就跑起来了。代码零改动。 步骤3用 Caddyfile 做正经配置生产 php-server 命令适合快速验证生产环境用 Caddyfile 更可控。一个标准的 Laravel Caddyfile 长这样逐行解释#Caddyfile ——放在项目根目录{# 全局选项块 frankenphp # 启用 FrankenPHP 模块#auto_https off # 本地开发想关 HTTPS 时取消注释}your-domain.com{# 你的域名Caddy 会自动申请并续签 Lets Encrypt 证书 root*public/# ★网站根目录指向 Laravel 的 public/encode zstd br gzip # 自动压缩响应zstd/brotli/gzip php_server # ★核心把请求交给内置 PHP 处理 # 自动处理 index.php rewrite、静态文件分流}逐行大白话-frankenphp在全局块里打开 FrankenPHP。-your-domain.com{}一个站点块。Caddy 最大的福利——自动HTTPS你写个真实域名它自动去 Lets Encrypt 申请证书、自动续期0配置。传统 Nginx 你得手搓 certbot。-root*public/告诉服务器网站根是 public/Laravel 的 web 根其它目录app/、vendor/、.env天然不暴露安全。-encode...响应压缩替代 Nginx 的 gzip on。-php_server一条指令顶 Nginx 一大段 location~\.php$fastcgi_pass。它内部等价于-请求的是存在的静态文件 →直接返回-否则 →rewrite 到 index.php 交给 PHP 跑 启动 frankenphp run # 它会自动找当前目录的 Caddyfile # 或指定 frankenphp run--config/path/to/Caddyfile 步骤4把 PHP-FPM 和 Nginx 的配置「翻译」过来 迁移时你旧配置里的设置要找到对应位置 ┌─────────────────────────────────────┬──────────────────┬────────────────────────────────────────────────────────┐ │ 你原来在哪配 │ 原来怎么写 │ FrankenPHP 里怎么配 │ ├─────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────┤ │ php.ini 的 │ │ 还是 php.ini。用 frankenphp run 时它读环境里的 │ │ memory_limit、upload_max_filesize │ php.ini │ php.iniDocker 镜像里在 │ │ 等 │ │ $PHP_INI_DIR/php.ini。改法不变 │ ├─────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────┤ │ │ │ Caddyfile 里 request_body{max_size20MB}或 │ │ Nginx client_max_body_size20M │ nginx.conf │ php.ini 的 │ │ │ │ upload_max_filesize/post_max_size两边取小 │ ├─────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────┤ │ FPM pm.max_children进程数 │ http://www.conf │ Caddyfile 的 frankenphp { num_threads N }控制 PHP ││ │ │ 线程数 │ ├─────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────┤ │ Nginx 静态文件缓存头 │ location~*│ Caddyfile 的 header 指令或交给 php_server 默认处理 │ │ │ \.(jpg|css)$ │ │ ├─────────────────────────────────────┼──────────────────┼────────────────────────────────────────────────────────┤ │ Nginx 反代/负载均衡 │ upstream │ Caddy 的 reverse_proxy但单机场景通常不需要了 │ └─────────────────────────────────────┴──────────────────┴────────────────────────────────────────────────────────┘ 设置线程数的写法{frankenphp{num_threads40# 类比 FPM 的 pm.max_children按内存和负载调}}步骤5迁移验证清单逐项打勾 零改动不代表零验证。挨个确认 #1)扩展齐不齐最常翻车 frankenphp php-cli-m|sort # 对照 composer.json 里所有ext-xxx#2)Laravel 的缓存先清避免旧路径残留 php artisan config:clearphp artisan route:clearphp artisan view:clear #3)生产优化缓存这些和 FPM 时一模一样不变 php artisan config:cache php artisan route:cache php artisan view:cache php artisan event:cache #4)文件权限storage 和 bootstrap/cache 要可写 chmod-R ugrw storage bootstrap/cache 功能层面要手动点一遍的-✅ 普通页面渲染GET-✅ 表单提交、文件上传POSTmultipart验证 read_post 那条链路-✅ Session/登录态Cookie验证 read_cookies-✅ 文件下载、大响应验证 ub_write 流式输出-✅ php artisan 命令照常能跑CLI 不受影响-✅ 队列 workerphp artisan queue:work和定时任务schedule:run——这些是独立进程迁移不影响它们照旧用 supervisor/cron 跑 步骤6队列、定时任务、Horizon 怎么办 这是迁移时容易忽略的FrankenPHP 只负责 HTTP 那一半。Laravel 的后台部分是独立的 # 定时任务crontab 不变照旧*****cd/path/to/laravelphp artisan schedule:run/dev/null21# 队列supervisor 配置不变照旧用 php-cli 跑 #/etc/supervisor/conf.d/laravel-worker.conf[program:laravel-worker]commandphp/path/to/laravel/artisan queue:work--sleep3--tries3注意 php 这里如果系统没装 PHP用 frankenphp php-cli/path/to/artisan queue:work。FrankenPHP 二进制本身就能当 php 命令用。 到这一步经典模式迁移完成代码零改动已经能上生产。性能通常已经比 NginxFPM 略好少了 FastCGI 协议开销且运维简化一个进程、自动 HTTPS。---第二部分榨性能Worker 模式非零改动但收益巨大 如果你想要 FrankenPHP 那个「快3-4倍」的效果上 worker 模式。这需要 Laravel Octane官方包专门适配 Swoole/RoadRunner/FrankenPHP。 为什么 worker 模式快回顾第7章 经典模式每个请求都要require autoload →启动整个 Laravel 框架注册几百个服务、解析路由、读配置→处理 → 全部销毁。Laravel 框架启动本身就要几十毫秒90%的时间花在重复启动框架上。 Worker 模式框架只启动一次常驻内存之后每个请求复用省掉那几十毫秒。 步骤1装 Octane composer require laravel/octane # 安装并选 FrankenPHP 作为 server php artisan octane:install--serverfrankenphp 这会装好 Octane 并配置成用 FrankenPHP 的 worker 模式。 步骤2启动 # 开发 php artisan octane:start--serverfrankenphp--watch # ↑改代码自动重载第11.5节那个热重载 # 生产 php artisan octane:start--serverfrankenphp--workers4--max-requests500#--workers worker 线程数一般CPU 核数 #--max-requests 每个 worker 处理 N 个请求后重启防内存泄漏的安全阀--max-requests 很重要它是「定期重启 worker」的兜底机制就算你代码有轻微泄漏跑500个请求就重启清零不至于 OOM。 步骤3代码体检这是「非零改动」的核心工作 Worker 模式下框架常驻第10章讲的所有泄漏陷阱都要排查。针对 Laravel 具体化 ①静态属性/单例累积// ☠️危险class SomeService{privatestaticarray $cache[];// worker 模式下永不清空}排查grep 你代码里的static属性容器、static$x[]。 ②容器里被你手动绑定的「请求作用域」单例// 如果你在 ServiceProvider 里这样绑过单例且它持有了请求数据$this-app-singleton(CurrentTenant::class,...);// 小心会跨请求残留Octane 提供了配置来每个请求后重置指定服务// config/octane.phpwarm[...],// 每个请求前预热的服务flush[...],// 每个请求后清空的服务 ←把有状态的放这listeners[RequestReceived::class[...],RequestTerminated::class[FlushTemporaryContainerInstances::class,// Octane 自带的清理],],③Octane 内存泄漏检测 Octane 自带工具帮你定位 # 它会报告哪些请求导致内存持续增长 php artisan octane:start--serverfrankenphp # 配合监控 memory_get_usage或用--max-requests 兜底 ④Laravel 官方已知要注意的点Octane 文档明确列出-不要用 $request 的全局 helper 缓存用 Auth::user()等没问题Octane 会重置但你自己static缓存了request()就会串台。-配置/容器单例里别存请求数据。-第三方包确认你用的包兼容 Octane大部分主流包已兼容。 步骤4迁移决策——到底用不用worker 模式 ┌──────────┬──────────────────────┬──────────────────────────────┐ │ 维度 │ 经典模式 │ Worker 模式(Octane)│ ├──────────┼──────────────────────┼──────────────────────────────┤ │ 代码改动 │ 零 │ 需排查无状态可能改少量代码 │ ├──────────┼──────────────────────┼──────────────────────────────┤ │ 性能 │ 比 FPM 略好 │ 比 FPM 快3-4倍 │ ├──────────┼──────────────────────┼──────────────────────────────┤ │ 迁移风险 │ 极低 │ 中状态泄漏风险 │ ├──────────┼──────────────────────┼──────────────────────────────┤ │ 适合 │ 想平滑替换 NginxFPM │ 高并发、追求极致吞吐 │ └──────────┴──────────────────────┴──────────────────────────────┘ 我的建议分两步走。先经典模式零改动上生产、稳住享受简化运维和自动 HTTPS跑一段时间确认无误之后再单独立项做 Octane 改造在 staging 环境充分压测和泄漏排查后再切。别一步到位把「换服务器」和「改架构」两件事混在一次上线里——出问题难定位。---完整迁移路线图一张图收尾 现状NginxPHP-FPMLaravel │ ├─【第一阶段零改动】─────────────────────────── │1.装 FrankenPHP二进制 or Docker dunglas/frankenphp │2.用 install-php-extensions 配齐扩展对照 composer.json★最易翻车 │3.写 Caddyfileroot →public/php_server 一行搞定 │4.把 php.ini/FPM/Nginx 设置翻译过来见对照表 │5.artisan config:cache/route:cache和原来一样 │6.队列/定时任务用 frankenphp php-cli 跑supervisor/cron 不变 │7.功能清单逐项验证POST/Session/上传/下载 │ →上生产。代码零改动运维简化自动 HTTPS性能略升 │ └─【第二阶段可选提速】──────────────────────────1.composer require laravel/octane2.artisan octane:install--serverfrankenphp3.★体检无状态static属性、请求作用域单例、连接事务状态4.config/octane.php 配 flush 清理有状态服务5.octane:start--workersN--max-requests500兜底防泄漏6.staging 压测内存监控确认无泄漏 →切生产。性能3-4倍 三句话记住1.经典模式真零改动root public/php_server 一行把它当更好用的 NginxFPM。2.迁移最大的坑是扩展没配齐先 frankenphp php-cli-m 对照 composer.json。3.要极致性能上 Octane worker 模式但那不是零改动——得排查第10章那些跨请求状态泄漏用--max-requests 兜底。