swoole中不能直接用全局数组传数据,因为多worker进程内存不共享,静态变量、$_session等无法跨进程访问;应使用swoole\table或redis共享数据,连接池需按worker独立初始化,子进程退出须监听sigchld回收,unix socket需注意权限、残留和超时。

为什么Swoole里不能直接用全局数组传数据
因为Swoole默认是多Worker进程模型,每个Worker是独立进程,内存不共享。你在一个Worker里往$GLOBALS['data']或static $cache里写值,另一个Worker完全看不到——这不是PHP语法问题,是操作系统级的隔离。
常见错误现象:在onReceive里存了用户ID到静态变量,下一次请求进另一个Worker,查不到;或者用file_put_contents('cache.txt')频繁读写,IO打满、并发一高就超时。
- 别指望
$_SESSION或$_COOKIE跨请求维持状态:HTTP无状态本质没变,Swoole只是换了个运行方式 - 协程内用
static变量也危险:协程销毁后变量还在,但下次协程启动可能复用旧值,尤其在max_request未触发重启时 - 真要临时存,优先用
Swoole\Table(单机)或Redis(分布式),它们天然支持多进程并发访问
Worker进程间怎么安全共享连接池
连接池(如MySQL、Redis)必须被所有Worker共用,否则每个Worker都建一堆连接,数据库很快被打爆。但直接new一个对象全局共享会出错——对象实例绑定在创建它的Worker进程里,其他Worker访问会报Connection refused或Segmentation fault。
正确做法是把连接池做成“按需创建 + 进程内单例”,而不是跨进程共享对象:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 在
onWorkerStart回调里初始化连接池,每个Worker自己持有一套连接 - 用
Swoole\Coroutine\Pool管理协程级连接,配合get()/put()自动回收,避免协程阻塞 - 不要在
onStart里初始化连接池:那是Manager进程上下文,它不处理请求,连不上数据库 - 如果必须跨Worker同步状态(比如限流计数),用
Swoole\Table的incr(),它是原子操作,不用额外加锁
子进程退出后,父进程怎么知道并清理资源
Swoole里用swoole_process创建子进程时,父进程默认收不到退出通知。如果你在onWorkerStart里fork了一个日志收集子进程,它挂了,父进程还傻等,就会导致资源泄漏甚至服务卡死。
必须显式监听SIGCHLD信号,并调用swoole_process::wait()回收:
- 在
onWorkerStart里注册pcntl_signal(SIGCHLD, function() { swoole_process::wait(false); }) -
swoole_process::wait(false)的false参数很重要:非阻塞,避免父进程停在这儿不动 - 别漏掉
pcntl_async_signals(true)(PHP 7.1+),否则信号可能被忽略 - 子进程退出码建议用
exit(128 + SIGSEGV)这类约定值,方便父进程区分异常类型
用Unix域套接字通信时,为什么客户端连不上
Unix域套接字(unix:///tmp/swoole.sock)常用于Worker和Task进程通信,但路径权限、文件残留、连接超时三个点最容易踩坑。
典型错误信息:Connection refused或No such file or directory。
- 确保
listen路径所在目录(如/tmp)对Worker进程用户可写,否则bind()失败,socket文件根本不会生成 - 程序异常退出后,socket文件可能残留,下次启动报
Address already in use:启动前先unlink($path)再listen - 客户端
connect()要设超时:$client->set(['connect_timeout' => 0.5]),否则默认阻塞几秒,拖慢整个请求链路 - 别混用TCP和Unix socket配置:TCP用
127.0.0.1:9501,Unix socket必须用unix:///path/to.sock,协议不互通
Swoole\Table的容量预设和max_request的协同。Table初始化时size设小了,后面set()会静默失败;而max_request设太大,Table里积累的脏数据就一直不清,最终OOM。这两者得一起看,不能只调一个。










