symfony 7 高并发必须换 swoole 或 roadrunner 运行时,php-fpm 无法支持;需配置协程模式、swoole http 传输器及协程化 i/o 组件,否则仍为同步阻塞。

Symfony 7 本身不处理并发请求,它只是个框架;真正决定并发能力的是你用的运行时环境——PHP-FPM 永远是同步阻塞模型,单请求占一个进程,根本谈不上“并发处理”。要让 Symfony 应用真正支持高并发请求(比如同时处理上千连接),必须换掉 PHP-FPM,换成协程运行时。
必须用 Swoole 或 RoadRunner 替代 PHP-FPM
这是硬性前提,没有商量余地。Symfony 7 的“虚拟线程”宣传,本质是依赖底层运行时提供的协程调度能力,不是 Symfony 自己实现的。
- Swoole 是目前最成熟、文档最全、与 Symfony 集成最顺的选项;RoadRunner 也不错,但对 Windows 支持弱、调试链路略长
- 安装后需启用
swoole扩展,并在config/packages/swoole.yaml中明确设mode: coroutine - 启动命令不再是
php -S或 Nginx + PHP-FPM,而是php bin/console swoole:server:start --async - 不改控制器代码也能生效——但前提是所有 I/O 操作(PDO 查询、
HttpClient::request()、Redis 调用)都走协程适配器,否则会退化为同步阻塞
HttpClient 在 Swoole 下自动协程化的条件
很多人以为装了 Swoole 就万事大吉,结果发现 $this->httpClient->request() 还是卡住——问题出在 HTTP 客户端没走协程通道。
- Symfony 默认的
HttpClient在 Swoole 环境下不会自动切换;必须显式配置使用swoole/http-client作为传输器 - 在
config/packages/framework.yaml中加:http_client: { default_options: { transport: 'swoole' } } - 确保已安装
swoole/http-client对应的适配器包(如symfony/http-client-swoole-transport) - 验证方式:发起两个耗时请求(如
sleep(2)的 mock API),看总耗时是否接近 2 秒(并发)而非 4 秒(串行)
别把 Messenger 当并发方案
用 Messenger 把请求发到队列再异步执行,这只是“任务卸载”,不是“并发请求处理”。它解决的是耗时操作阻塞响应的问题,不是提升服务器吞吐量。
-
$bus->dispatch(new SendNotificationMessage())立即返回,但请求本身仍是同步完成的 - 后台
messenger:consume进程还是单线程(或有限 worker 数)拉取消息,无法应对瞬时大量连接 - 它适合解耦逻辑、削峰填谷,但不能替代 Swoole 解决 C10K 问题
- 混用时注意:Swoole 环境下
messenger:consume必须单独跑在普通 PHP-FPM 或 CLI 模式,不能和 HTTP server 共享协程上下文
真正难的不是配 Swoole,而是确认每个依赖组件(数据库驱动、缓存客户端、日志写入器)都支持协程非阻塞调用——漏掉一个,整条链路就卡死。很多团队卡在这一步,最后退回 PHP-FPM,不是 Symfony 不行,是生态适配没做全。











