单线程reactor在swoole中特指swoole_process模式下仅有一个reactor线程负责accept、read就绪通知、write就绪通知,不执行php业务逻辑;swoole_base下reactor与worker同线程成瓶颈;swoole_thread已废弃,本质是单reactor+多worker线程;真正多reactor仅在swoole_base配合reactor_num生效,现代推荐协程+单reactor。

单线程Reactor在Swoole里实际就是SWOOLE_PROCESS模式下的默认行为
不是所有“单线程”都等于“只用一个PHP线程”——Swoole的SWOOLE_PROCESS模式下,主线程确实是单Reactor线程,但它会fork出多个worker进程来处理业务。这个Reactor线程本身只干三件事:accept新连接、read数据就绪通知、write发送准备就绪通知。它不执行PHP代码,也不做业务逻辑。
常见错误现象:你启用了SWOOLE_PROCESS但没设worker_num,结果压测时CPU只跑满1个核,QPS卡在几千上不去;或者你在Reactor线程里直接调用sleep()或阻塞IO,整个服务瞬间假死。
- Reactor线程永远不能执行耗时PHP操作(比如
file_get_contents、curl_exec、数据库查询) - 它只响应内核事件(EPOLLIN/EPOLLOUT),靠
epoll_wait驱动,所以必须保持非阻塞 - 如果你用
SWOOLE_BASE模式,那Reactor和Worker是同一个线程,此时“单线程Reactor”就真成了瓶颈——所有连接共用一个event loop + 一个PHP执行栈
SWOOLE_THREAD模式下Reactor仍是单线程,但Worker由线程池接管
Swoole从4.4.0起已废弃SWOOLE_THREAD,但很多老项目还在用。它的本质不是“多Reactor”,而是“单Reactor + 多Worker线程”。Reactor线程依然只有一个,负责监听和分发;区别在于:收到数据后,它把任务投递进一个线程安全的任务队列,由thread_num指定的线程池里的Worker线程去执行PHP回调(如onReceive)。
容易踩的坑:
- PHP扩展本身不是线程安全的(比如
mysqli、pdo_mysql),在Worker线程里直接new一个PDO对象大概率崩溃 - 全局变量、静态变量在线程间不共享,你以为的“单例”其实在每个线程里都有一份副本
-
SWOOLE_THREAD模式下无法使用协程(Swoole\Coroutine),因为协程调度器和线程模型冲突
真正意义上的“多Reactor”只存在于SWOOLE_BASE + reactor_num配置中
这是最容易被误解的一点:Swoole的reactor_num参数只有在SWOOLE_BASE模式下才生效。它会让Swoole创建多个Reactor线程,每个线程绑定一个CPU核心,各自独立运行epoll_wait,分别监听一部分fd(通过哈希分配)。但这不是“主从Reactor”,没有Acceptor分离——每个Reactor线程都同时处理accept、read、write。
本文档主要讲述的是React Native For Android 源码编译;希望对大家会有帮助;感兴趣的朋友可以过来看看
使用场景非常有限:
- 你有大量短连接(比如HTTP API网关),且连接建立/断开频率极高
- 你的业务逻辑极轻(比如纯转发、简单鉴权),不需要Worker进程/线程介入
- 你明确知道每个Reactor线程的负载要靠
reactor_num手动均分,而不是靠OS调度
注意:reactor_num设得比CPU核心数还多,反而会因上下文切换导致性能下降;设得太少(比如reactor_num=1)又退化回单点瓶颈。
现代Swoole(v5.x)推荐用协程+单Reactor,而非多Reactor或多线程
当前主流做法是关闭reactor_num、禁用SWOOLE_THREAD,用SWOOLE_BASE或SWOOLE_PROCESS配合协程。此时Reactor线程仍是单个,但它不再把任务扔给阻塞式Worker,而是唤醒对应的协程栈去执行co::sleep、co::mysql等异步操作。协程让单线程能并发处理数万连接,且无锁、无上下文切换开销。
复杂点在于:协程不是透明的。比如你写了个同步风格的Composer包,它内部用了fsockopen,在协程环境里就会阻塞整个Reactor线程——这种地方必须显式改造成Swoole\Coroutine\Http\Client或加go(function() { ... })包裹。










