frankenphp 通过进程内集成与 worker 模式显著提升 sse 可靠性与实时性,需手动关闭 output_buffering、zlib 压缩和代理缓冲,并采用长循环+信号监听的推送设计。

是的,迁到 FrankenPHP 后 SSE 推送不仅更稳,而且延迟明显降低——但前提是关掉所有缓冲层并用对 worker 模式。它不是“自动变快”,而是消除了传统 Nginx + PHP-FPM 链路里那几道卡住流式响应的墙。
为什么 FrankenPHP 能让 SSE 更可靠
传统部署中,SSE 卡住的根因是多层缓冲叠加:PHP 自身的 output_buffering、zlib 压缩、Nginx 的 proxy_buffering、甚至 Cloudflare 的中间层。FrankenPHP 把 Web 服务和 PHP 运行时合在一个进程里,天然绕开了 FastCGI 转发和 Nginx 代理这两道最常出问题的环节。
- HTTP/3 和原生 keep-alive 支持让长连接更稳定,
Connection: keep-alive不再被中间件悄悄改写 - 没有
fastcgi_pass转发,也就不存在 Nginx 等待完整响应才转发的逻辑,echo "data:...\n\n"写完立刻走 TCP 发出去 - worker 模式下,PHP 进程常驻,
ob_start()、ob_end_clean()等缓冲操作只需初始化一次,后续每次推送都是“直写”
必须手动关掉的三个缓冲开关
FrankenPHP 不会自动帮你关缓冲——它默认行为仍兼容 classic 模式(类似 FPM),所以这些得自己配:
- 在 PHP 脚本开头加:
ini_set('output_buffering', 'off');和ini_set('zlib.output_compression', false); - 调用
ob_end_clean();清空已激活的输出缓冲,再ob_implicit_flush(false);(别开隐式刷新) - 在 Caddyfile 的路由块里加:
header_up X-Accel-Buffering "no"(等效于 Nginx 的proxy_buffering off)
worker 模式下 SSE 的正确写法
用 classic 模式跑 SSE,每个请求仍要重走一遍 bootstrap,性能提升有限;只有开启 worker 模式,才能真正发挥 FrankenPHP 的优势:
- 启动命令必须带
--workers参数,例如:frankenphp run --workers=4 - SSE 脚本不能写成“一次请求全干完”,而应设计为长循环 + 信号监听,比如用
pcntl_signal_dispatch()或 Redis Pub/Sub 触发推送 - 避免在循环里重复调用
new PDO()或app(),worker 进程生命周期内复用连接和容器实例 - 记得设
set_time_limit(0),但不要放在循环里反复调——一次就够了
最容易被忽略的一点:FrankenPHP 的 worker 模式不支持 register_shutdown_function() 在每次推送后执行清理,因为进程不销毁。如果你在 SSE 脚本里依赖这个函数做资源释放,得改用 pcntl_signal() 或显式 close() 来管理。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











