Swoole进程退出主因是未正确处理守护模式与事件循环生命周期,如误用exit、未捕获异常、daemonize后无日志;定时器不触发因注册时机错或阻塞导致事件循环卡死;连接池变慢多因max_idle_time过大致连接堆积;WSS需正确配置证书路径与权限,而非启用OpenSSL扩展。

为什么 swoole_http_server->start() 后进程立刻退出?
根本原因通常是没正确处理守护进程模式和事件循环生命周期。Swoole 不是普通 PHP 脚本,start() 之后它接管控制权,一旦主逻辑结束(比如脚本末尾执行完)、或遇到未捕获的致命错误,worker/master 进程就会退出。
- 检查是否误用了
exit()或die()在回调里(比如在onRequest中直接exit('ok')),这会杀死当前 worker 进程 - 确认没在
onStart或onWorkerStart中抛出未捕获异常 —— Swoole 1.x 会静默退出,4.x+ 会打印Fatal error: Uncaught ...但进程仍挂掉 - 若启用了
daemonize => 1,务必配合log_file配置,否则 stderr 被重定向,错误全丢进黑洞 - 开发阶段先关掉
daemonize,用php server.php前台运行,错误直接可见
swoole_timer_tick() 定时器不触发?别漏掉这个配置
常见错觉是“写了定时器就该跑”,实际它依赖 event loop 正常运转。最隐蔽的坑是:你在非协程环境(比如同步阻塞 I/O、sleep()、或 MySQLi 普通连接)里调用了它,导致事件循环卡死。
-
swoole_timer_tick()必须在 Swoole 的 event loop 内注册,不能在onStart里调(此时 loop 尚未启动),应放在onWorkerStart或任意已进入协程上下文的位置 - 如果用了
max_request且值过小(如10),worker 处理完 10 个请求就被重启,定时器随之销毁 —— 改成0(不限制)或足够大的数 - 注意时间单位是毫秒,
swoole_timer_tick(5000, ...)是 5 秒,不是 5 秒钟后只执行一次(那是swoole_timer_after()) - 协程版定时器
Swoole\Timer::tick()更安全,但必须在协程内调用,否则报ERROR swManager_check_exit_status: worker#0 abnormal exit, status=0, signal=0
协程 MySQL 连接池为啥越用越慢?关键在 max_idle_time
很多人以为连接池只要设了 max_connections 就万事大吉,结果压测几分钟后 QPS 断崖下跌。真实瓶颈往往不是连接不够,而是闲置连接没及时回收,占着内存又不释放底层 socket。
-
max_idle_time默认是60秒,意味着一个空闲连接至少活 60 秒才可能被销毁 —— 高并发下大量 idle 连接堆积,触发系统文件描述符耗尽(Too many open files) - 建议设为
10~30秒,尤其在短连接、突发流量场景;若业务明确有长周期任务,再单独建专用连接,别混进池子 - 不要盲目调大
max_connections,先看swoole_server->stats()里的connection_num和task_worker_num是否真打满 - 记得用
$pool->get()+$pool->put($conn)成对调用,漏掉put会导致连接永远不归还 —— 这比超时更致命
如何让 swoole_websocket_server 支持 WSS?别碰 OpenSSL 扩展配置
想上 WSS,第一反应常是去改 php.ini 开 openssl,其实完全没必要。Swoole 的 TLS 是基于 libssl 库做的,跟 PHP 的 OpenSSL 扩展无关,真正要动的是 server 构造参数和证书路径权限。
- 必须传入
ssl_cert_file和ssl_key_file两个绝对路径,相对路径会静默失败;检查ls -l确认 webserver 用户(如 www-data)有读权限 - 证书链要完整:如果用了 Let’s Encrypt,
ssl_cert_file应该是fullchain.pem,不是cert.pem;否则浏览器提示“证书不受信任” - 端口别设成
443直接跑 —— 普通用户无权绑定<1024端口,用反向代理(Nginx)更稳妥,Swoole 只监听9501等高位端口 - 开启
open_http2_protocol => true并不会自动启用 HTTP/2 over TLS,WSS 本质还是 WebSocket over TLS,HTTP/2 是另一套协商机制
真正难调的从来不是开关配置,而是当多个协程共享资源、定时器与连接池交织、TLS 握手又卡在某个中间状态时,日志里只有一行 Segmentation fault —— 那时候得翻 core dump,而不是再加一行 echo。










