onRequest不触发主因是请求未达HTTP解析层:TCP连接失败、HTTP格式错误(如400)、协程阻塞或HTTPS配置缺失,导致根本无法进入PHP回调。

onRequest 不触发,八成不是代码写错了,而是请求压根没进到 HTTP 协议解析那一步——它卡在了 TCP 层或更早的网络链路里。
HTTP Server 启动成功但 onRequest 不回调
常见现象:swoole_http_server->start() 没报错,netstat -tlnp | grep 9501 显示端口已监听,但 curl 或浏览器访问完全没日志、没响应、onRequest 函数体里的 var_dump 一句都不执行。
根本原因:Swoole 的 swoole_http_server 只响应符合 HTTP 协议格式的完整请求。它不是裸 TCP Server,不接受任意字节流。
- 用
telnet 127.0.0.1 9501手动发数据?必须严格按 HTTP 格式写,比如:GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n(注意两个\r\n) - 浏览器访问却没触发?先检查是否发了
favicon.ico请求干扰判断;再确认 URL 是http://127.0.0.1:9501/而非https(没配 SSL 时 HTTPS 会静默失败) - 用
curl测试务必加-v看真实请求头,避免被重定向或代理截断
onRequest 触发前就被 400 Bad Request 拦截
现象:服务端无任何自定义日志输出,但客户端收到 HTTP/1.1 400 Bad Request 响应。这说明 Swoole 的 C 层协议解析器已经介入,并因格式错误直接拒绝,根本不会走到 PHP 层的 onRequest 回调。
典型触发条件:
- HTTP 请求行缺失或格式错误(如写成
GET/ HTTP/1.1少了空格) -
Content-Length声明为 100,但实际 body 不足或超长 - 使用
Transfer-Encoding: chunked但分块格式非法(常见于手动拼接或调试工具误发) - Header 行含不可见控制字符(如
\0、\x01),Wireshark 抓包才能发现
验证方式:临时加个 onStart 回调,在里面 echo "server started\n",确认进程活着;再用 tcpdump -i lo port 9501 -A 抓原始字节流,比对是否符合 RFC 7230。
协程环境里 onRequest 被阻塞或吞掉异常
现象:onRequest 函数体开头有 var_dump('in'),但始终不打印;或者只打印一次后彻底失联。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
本质是 PHP 层崩溃未透出,而 Swoole 默认静默处理:
- 函数体内抛出未捕获异常(如调用不存在的方法、数组越界),且
swoole.display_errors关闭 → 请求无声失败 - 协程中用了
sleep()、file_get_contents()等同步阻塞函数 → 整个 worker 进程卡死,后续请求全积压 - 在
onRequest里直接exit或die→ 当前协程终止,但不会报错,也不会触发onClose
实操建议:
- 启动前确保
ini_set('swoole.display_errors', '1')或配置文件设swoole.display_errors = On(仅开发环境) - 所有 IO 操作强制替换为协程版:
Swoole\Coroutine\Http\Client替curl_exec,Swoole\Coroutine\FileSystem::readFile替file_get_contents - 给
onRequest包一层try/catch,并在catch里显式$response->status(500)->end("error")
HTTPS 配置错误导致 onRequest 彻底不进入
现象:HTTP 请求能触发 onRequest,但换 https:// 就超时或连接被重置,且服务端零日志。
关键点:swoole_http_server 默认只跑 HTTP;启用 HTTPS 必须显式传入证书路径,且证书文件权限、格式、链完整性都必须正确。
- 配置项缺一不可:
ssl_cert_file、ssl_key_file,二者路径必须绝对路径,且 PHP 进程有读取权限 - 证书不能是 PEM 里混了私钥和证书内容的“all-in-one”文件(某些 Let's Encrypt 工具生成的),要拆成两个独立文件
- 用
openssl x509 -in cert.pem -text -noout和openssl rsa -in key.pem -check分别验签 - 若用自签名证书,客户端 curl 需加
-k,否则 TLS 握手失败,请求根本不会送到 HTTP 解析层
最省事的验证法:先用 HTTP 跑通 onRequest,再只增加 SSL 配置项并重启,观察 start() 是否返回 false 或报 SSL context setup failed 类错误。
真正难排查的,往往不是 onRequest 里逻辑写错了,而是它连被执行的机会都没有——网络层、协议层、配置层任一环节断开,都会让这个回调变成“幽灵函数”。盯住 TCP 连接是否建立、HTTP 请求是否合规、PHP 进程是否真的收到了字节流,比翻业务代码更快定位问题。

















