最简swoole http服务器需5行代码:new swoole\http\server→on('request')→$response->end(),须显式绑定回调并调用end(),禁用echo/var_dump。

直接上手写个能跑的 Swoole HTTP 服务器
刚装完 swoole,执行 php --ri swoole 确认扩展已加载,就能写最简 HTTP 服务——不需要框架、不依赖路由库,5 行代码启动一个响应 “Hello Swoole” 的服务。
常见错误是照抄旧版文档用 Swoole\Http\Server 但没加 on('request', ...) 回调,结果服务起来却无响应;或者用了协程风格写法(如 Co\Http\Server)但 PHP 版本低于 8.1 或没开启 enable_coroutine=1,直接报错。
-
new Swoole\Http\Server('0.0.0.0', 9501)是最稳的入门选择,PHP 7.2+、Swoole 4.4+ 均支持 - 必须显式绑定
on('request', function ($request, $response) { ... }),否则请求会挂起无返回 -
$response->end()必须调用,漏掉就连接一直挂着,curl 会卡住或超时 - 别在回调里用
echo或var_dump,它们不输出到 HTTP 响应体,只会打到终端或日志
<?php
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->on('request', function ($request, $response) {
$response->header('Content-Type', 'text/plain');
$response->end("Hello Swoole\n");
});
$server->start();
用 Swoole 实现异步 MySQL 查询别踩这些坑
想用 Swoole\Coroutine\MySQL 替代 mysqli 做非阻塞查询?得先确认运行环境:PHP 必须启用协程(cli 模式下默认开,fpm 下完全不可用),且不能在同步上下文(比如普通 onRequest 回调里混用同步 DB 类)中调用协程客户端。
典型报错是 ERROR swManager_loop: fatal error: unknown signal 0 或直接 segfault,多因在非协程环境调了 go(),或 MySQL 连接未在协程内创建。
- 所有协程 MySQL 操作必须包裹在
go(function () { ... })或协程上下文(如Co\Http\Server的 request 回调)中 -
$mysql = new Swoole\Coroutine\MySQL()必须在协程内 new,不能复用跨协程的实例 -
$mysql->connect()返回false时不等于失败,要检查$mysql->connect_errno;成功后才可执行query() - 不要用
mysql_real_escape_string,协程 MySQL 自动处理参数绑定,推荐用prepare + execute
为什么 Swoole WebSocket 服务收不到消息?检查这几点
WebSocket 服务启动了、前端 new WebSocket('ws://127.0.0.1:9502') 能连上,但 on('message', ...) 死活不触发——大概率是前端发的数据格式不对,或服务端没正确设置握手响应头。
常见误区是以为 WebSocket 和 HTTP 一样随便发字符串就行,其实浏览器 WebSocket API 默认只发文本帧(opcode=1),而 Swoole 默认接收所有帧类型,但若客户端发的是二进制(比如用 send(arrayBuffer)),服务端需显式判断 $frame->data 类型。
- 确保前端发的是文本消息:
ws.send('hello'),不是ws.send(new ArrayBuffer()) - 服务端
on('open', ...)不需要手动handshake,Swoole 已封装;但若自定义onHandShake,必须完整返回 101 切换协议头 -
$server->push($fd, $data)发送前,务必确认$fd存在且未关闭(可用$server->exist($fd)检查) - 调试时用
wscat -c ws://127.0.0.1:9502比浏览器更干净,避免前端 JS 逻辑干扰
reload 失败、worker 进程僵死?别忽略 Swoole 的进程模型约束
kill -USR1 $master_pid 或 $server->reload() 后服务没更新代码、甚至部分 worker 卡住不响应——根本原因是 Swoole 的 reload 只重启 worker 进程,不重启 master / manager,而全局变量、单例对象、静态属性在 worker 重启后仍保留在内存里,不会自动重置。
尤其当代码里写了 static $cache = [] 或 new SomeSingleton(),reload 后新 worker 会沿用旧值,导致行为异常。这不是 bug,是设计使然。
- 所有状态类数据(缓存、连接池实例、计数器)必须在
onWorkerStart中初始化,不能放在文件顶层或类静态属性里 - 避免在
onWorkerStart外建立长连接(如 Redis、MySQL),否则 reload 后旧连接残留,新 worker 可能复用失效句柄 - 使用
Server::TASK时,task 进程不参与 reload,其内部状态完全独立,别指望它和 worker 共享变量 - 调试 reload 问题时,用
ps aux | grep php看 worker 进程启动时间是否更新,比看日志更直接










