概述
什么是 FrankenPHP Worker 模式?
FrankenPHP 是一个现代的 PHP 应用服务器,它将 PHP 与 Caddy web 服务器集成在一起。Worker 模式允许 PHP 进程常驻内存,类似于 Node.js 或 Go 的运行方式。
性能提升 30-50%
减少 PHP 启动开销,请求响应更快
内存效率高
进程复用,降低内存占用
连接池
数据库连接在请求间复用
启动更快
应用只启动一次,后续请求直接处理
架构对比
传统 PHP-FPM 模式:
请求 → Nginx/Caddy → PHP-FPM → 启动PHP → 执行脚本 → 销毁PHP
↓
响应
FrankenPHP Worker 模式:
请求 → FrankenPHP → Worker Pool → 执行脚本 → 重置状态 → 等待下一个请求
↑____________重用____________↓
安装 FrankenPHP
方式1: 官方安装脚本(推荐)
curl https://frankenphp.dev/install.sh | sh
方式2: 使用 Docker
docker pull dunglas/frankenphp
方式3: 下载二进制文件
访问 FrankenPHP Releases 下载适合你系统的版本。
验证安装
frankenphp version
项目文件说明
新增文件
- worker.php - Worker 模式入口文件
- 处理 FrankenPHP 的 worker 循环
- 管理请求计数和生命周期
- 实现优雅退出机制
- src/Core/WorkerRequestHandler.php - 请求处理器
- 请求前准备(重置状态)
- 请求处理(调用路由)
- 请求后清理(防止泄漏)
- routes.php - 路由配置文件
- 从 index.php 抽取的路由定义
- 在 Worker 模式和传统模式下共享
- Caddyfile.frankenphp - FrankenPHP 配置
- Worker 配置
- 静态资源处理
- 安全头部设置
- start_frankenphp.sh - 启动脚本
- 环境检查
- 配置管理
- 进程启动
修改文件
- src/Core/SessionManager.php
- 新增 resetForNextRequest() 方法
- 新增 ensureSessionStarted() 方法
- 支持 Worker 模式下的会话重置
- src/Core/DIContainer.php
- 新增 clearRequestCache() 方法
- 支持请求级别缓存清理
- src/Core/ErrorHandler.php
- 新增 resetRequestState() 方法
- 支持错误处理器状态重置
启动服务
开发环境
# 使用启动脚本(推荐)
./start_frankenphp.sh
# 或者直接运行
frankenphp php-server --worker worker.php --listen :8080
生产环境(使用 Caddyfile)
# 使用启动脚本选择模式1
./start_frankenphp.sh
# 或者直接运行
frankenphp run --config Caddyfile.frankenphp
环境变量配置
# Worker 最大请求数(默认 1000)
export FRANKENPHP_MAX_REQUESTS=1000
# Worker 最大运行时间(秒,默认 3600)
export FRANKENPHP_MAX_LIFETIME=3600
配置说明
Caddyfile 配置
编辑 Caddyfile.frankenphp:
localhost:443 {
php_server {
# Worker 文件路径
worker /path/to/worker.php
# Worker 线程数(建议:CPU核心数 × 2)
num_threads 4
# 文档根目录
root /path/to/zhichai.php
}
}
Worker 配置
Worker 会自动根据以下条件重启:
- 达到最大请求数(默认 1000)
- 达到最大运行时间(默认 3600 秒)
- 发生致命错误
可以通过环境变量调整:
export FRANKENPHP_MAX_REQUESTS=2000
export FRANKENPHP_MAX_LIFETIME=7200
监控和调试
查看 Worker 日志
# 实时查看日志
tail -f debug.log
# 查看访问日志
tail -f logs/caddy_access.log
# 查看错误日志
tail -f logs/caddy_error.log
Worker 统计信息
Worker 每处理 100 个请求会输出统计信息:
[Worker] 统计 - 请求数: 100, 运行时间: 120s, 内存: 45.2MB, 峰值: 52.3MB
调试模式
开发环境下,在 config.php 中启用调试:
'app' => [
'debug' => true, // 启用详细日志
]
常见问题
1. 会话状态泄漏
症状: 用户A的请求能看到用户B的数据
原因: SessionManager 未正确重置
解决: 确保 resetForNextRequest() 被调用
原因: SessionManager 未正确重置
解决: 确保 resetForNextRequest() 被调用
2. 内存持续增长
症状: Worker 内存使用持续增加
原因: 内存泄漏或循环引用
解决:
原因: 内存泄漏或循环引用
解决:
- 降低 FRANKENPHP_MAX_REQUESTS
- 检查代码中的循环引用
- 使用 gc_collect_cycles() 强制垃圾回收
3. 数据库连接错误
症状: Redis/SQLite 连接失败
原因: 连接在 Worker 生命周期中断开
解决: RedisManager 和 SQLiteManager 会自动重连
原因: 连接在 Worker 生命周期中断开
解决: RedisManager 和 SQLiteManager 会自动重连
4. 静态资源404
症状: CSS/JS 文件无法加载
原因: Caddyfile 配置错误
解决: 确保 root 指向正确的目录
原因: Caddyfile 配置错误
解决: 确保 root 指向正确的目录
性能对比
基准测试
使用 Apache Bench 进行测试(100 并发,1000 请求):
| 模式 | 请求/秒 | 平均延迟 | 内存占用 |
|---|---|---|---|
| PHP-FPM | 850 req/s | 118ms | 120MB |
| FrankenPHP Worker | 1250 req/s | 80ms | 85MB |
| 提升 | +47% | -32% | -29% |
实际场景
- 首页加载: 从 150ms 降至 95ms
- 话题列表: 从 120ms 降至 75ms
- 用户登录: 从 200ms 降至 130ms
安全考虑
1. 状态隔离
确保每个请求完全独立:
// ✅ 正确:使用局部变量
function handleRequest() {
$user = getCurrentUser();
// ...
}
// ❌ 错误:使用全局变量或静态变量
static $cachedUser;
global $currentUser;
2. 敏感数据清理
请求结束后清理敏感数据:
public function cleanupRequest() {
// 清理密码等敏感数据
unset($_POST['password']);
unset($_POST['token']);
}
3. 资源释放
及时释放资源:
// 关闭文件句柄
fclose($file);
// 清理临时文件
unlink($tempFile);
// 释放大对象
unset($largeArray);
回滚到 PHP-FPM
如果遇到问题需要回滚:
1. 停止 FrankenPHP
pkill frankenphp
2. 启动 PHP-FPM
# 使用 PHP 内置服务器
php -S localhost:8080
# 或使用 Nginx + PHP-FPM
sudo systemctl start php-fpm
sudo systemctl start nginx
3. 恢复 Caddy 配置
# 使用原有的 Caddyfile
caddy run --config Caddyfile
参考资料
获取帮助
如果遇到问题:
- 查看日志文件 debug.log
- 检查 Worker 统计信息
- 在项目 Issues 中提问
- 参考本文档的常见问题部分
更新日志
v1.0.0 (2025-01-20)
- ✨ 初始实现 FrankenPHP Worker 模式
- ✅ SessionManager Worker 支持
- ✅ DIContainer 请求缓存清理
- ✅ ErrorHandler 状态重置
- 📚 完整文档和部署指南
