在 think-swoole 中,如果你不想把 RPC 逻辑混入全局的 swoole.receive 事件中,最直接、最高效的做法是利用 Swoole 原生的 onReceive 回调,在 config/swoole.php 的多端口监听 (listen) 中直接闭包绑定。
这种做法属于“物理隔离”,RPC 的数据流完全不经过 TP6 的事件分发,性能反而更好。
以下是具体的改造方案:
1. 彻底改造 config/swoole.php
我们直接在 listen 配置中,利用 callbacks 参数绑定 Swoole 原生的 receive 事件。
php
<?php
// config/swoole.php
use app\common\rpc\RpcDispatcher;
return [
'server' => [
'host' => '0.0.0.0',
'port' => 80, // Web 端口
'mode' => SWOOLE_PROCESS,
'sock_type' => SWOOLE_SOCK_TCP,
'options' => [
'worker_num' => swoole_cpu_num(),
],
// 🌟 核心:在此处直接接管 TCP 接收
'listen' => [
[
'host' => '0.0.0.0',
'port' => 9502, // RPC 专门端口
'sock_type' => SWOOLE_SOCK_TCP,
'options' => [
'open_eof_check' => true,
'package_eof' => "\r\n",
],
// 🚀 不走 TP6 事件,直接绑定 Swoole 原生回调
'callbacks' => [
\Swoole\Constant::EVENT_RECEIVE => function ($server, $fd, $reactorId, $rawData) {
// 1. 实例化或从容器中获取调度器
/** @var RpcDispatcher $dispatcher */
$dispatcher = app(RpcDispatcher::class);
// 2. 调度并解析
$responsePayload = $dispatcher->dispatch($rawData);
// 3. 直接发送回客户端
$server->send($fd, $responsePayload);
}
]
],
],
],
// 其他配置保持默认...
];
请谨慎使用此类代码。
2. 移除旧的事件监听(清理工作)
既然不使用事件监听了,你需要做两件事来保持项目干净:
删除文件:可以安全删除
app\listener\RpcReceiveListener.php。清理配置:检查
app\event.php,把之前加在swoole.receive里的配置删掉,恢复原样:php
'listen' => [ // 'swoole.receive' => [...] <- 删掉这行 ],请谨慎使用此类代码。
3. 解析器 RpcDispatcher.php 保持不变
上一步创建的 app\common\rpc\RpcDispatcher.php 代码完全不需要修改。因为它只负责接收字符串、解析、调用、返回字符串,和底层是用事件还是用原生回调毫无关系(这也是高内聚低耦合的好处)。
💡 为什么这种方案更推荐?
零干扰:传统的
swoole.receive事件是全局的。如果你的 Web 服务也用到了 WebSocket 或者其他 TCP 长连接,全局事件会收到所有端口的数据,你必须在里面写if ($port === 9502)去过滤 [1]。而现在的方案让 9502 端口的数据在底层就独立处理。性能更高:不走 TP6 的
Event::trigger()意味着少了一层框架的动态动态解析和观察者遍历,TCP 数据直达你的RpcDispatcher,执行效率更高。结构清晰:RPC 的协议配置(EOF、端口)和它的核心接收逻辑都在
config/swoole.php的同一个数组里,代码聚合度极高。
你现在可以重启 php think swoole 服务测试一下,客户端的同步/异步调用依然可以完美无缝运行。