发布于2026-07-07 阅读(0)
扫一扫,手机访问
在Swoole开发中,有个常见的误区:很多人试图用全局数组来传递数据,但行不通——因为多Worker进程内存不共享。说到底,这不是PHP语法的问题,而是操作系统级的隔离。当你在一个Worker里往$GLOBALS['data']或static $cache里写值,另一个Worker根本看不到。典型现象:onReceive里存了用户ID到静态变量,下一次请求却跑进了另一个Worker,查不到;或者用file_put_contents('cache.txt')频繁读写,IO打满、并发一高就超时。

别指望$_SESSION或$_COOKIE能跨请求维持状态——HTTP的无状态本质没变,Swoole只是换了个运行方式。协程内用static变量同样危险:协程销毁后变量还在,但下次协程启动可能复用旧值,尤其在max_request未触发重启时。真要临时存,优先用SwooleTable(单机)或Redis(分布式),它们天然支持多进程并发访问。
连接池(如MySQL、Redis)必须被所有Worker共用,否则每个Worker都建一堆连接,数据库很快被打爆。但直接new一个对象全局共享会出错——对象实例绑定在创建它的Worker进程里,其他Worker访问会报Connection refused或Segmentation fault。正确做法是“按需创建 + 进程内单例”:
onWorkerStart回调里初始化连接池,每个Worker自己持有一套连接SwooleCoroutinePool管理协程级连接,配合get()/put()自动回收,避免协程阻塞onStart里初始化连接池——那是Manager进程上下文,它不处理请求,连不上数据库SwooleTable的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:///tmp/swoole.sock)常用于Worker和Task进程通信,但路径权限、文件残留、连接超时三个点最容易踩坑。典型错误信息:Connection refused或No such file or directory。
listen路径所在目录(如/tmp)对Worker进程用户可写,否则bind()失败,socket文件根本不会生成Address already in use:启动前先unlink($path)再listenconnect()要设超时:$client->set(['connect_timeout' => 0.5]),否则默认阻塞几秒,拖慢整个请求链路127.0.0.1:9501,Unix socket必须用unix:///path/to.sock,协议不互通实际部署中,最常被忽略的是SwooleTable的容量预设和max_request的协同。Table初始化时size设小了,后面set()会静默失败;而max_request设太大,Table里积累的脏数据就一直不清,最终OOM。这两者得一起看,不能只调一个。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8