Files
jianfeng-server/vendor/topthink/think-swoole/src/concerns/InteractsWithRpc.php
2025-10-02 10:33:06 +08:00

123 lines
3.4 KiB
PHP
Executable File

<?php
namespace think\swoole\concerns;
use Swoole\Server;
use think\App;
use think\Event;
use think\helper\Str;
use think\swoole\contract\rpc\ParserInterface;
use think\swoole\rpc\client\Pool;
use think\swoole\rpc\JsonParser;
use think\swoole\rpc\server\Dispatcher;
/**
* Trait InteractsWithRpc
* @package think\swoole\concerns
* @property App $app
* @method Server getServer()
*/
trait InteractsWithRpc
{
protected $rpcEvents = [
'connect',
'receive',
'close',
];
protected $isRpcServer = false;
protected function prepareRpc()
{
if ($this->isRpcServer = $this->getConfig('rpc.server.enable', false)) {
$host = $this->getConfig('server.host');
$port = $this->getConfig('rpc.server.port', 9000);
$rpcServer = $this->getServer()->addlistener($host, $port, SWOOLE_SOCK_TCP);
$rpcServer->set([
'open_eof_check' => true,
'open_eof_split' => true,
'package_eof' => ParserInterface::EOF,
]);
$this->setRpcServerListeners($rpcServer);
}
$this->onEvent('workerStart', function () {
if ($this->isRpcServer) {
$this->bindRpcParser();
$this->bindRpcDispatcher();
}
$this->bindRpcClientPool();
});
}
/**
* @param Server\Port $server
*/
protected function setRpcServerListeners($server)
{
foreach ($this->rpcEvents as $event) {
$listener = Str::camel("on_rpc_$event");
$callback = method_exists($this, $listener) ? [$this, $listener] : function () use ($event) {
$this->triggerEvent("rpc." . $event, func_get_args());
};
$server->on($event, $callback);
}
}
protected function bindRpcClientPool()
{
if (!empty($clients = $this->getConfig('rpc.client'))) {
$this->app->instance(Pool::class, new Pool($clients));
//引入rpc接口文件
if (file_exists($rpc = $this->app->getBasePath() . 'rpc.php')) {
include_once $rpc;
}
}
}
protected function bindRpcDispatcher()
{
$services = $this->getConfig('rpc.server.services', []);
$this->app->make(Dispatcher::class, [$services]);
}
protected function bindRpcParser()
{
$parserClass = $this->getConfig('rpc.server.parser', JsonParser::class);
$this->app->bind(ParserInterface::class, $parserClass);
$this->app->make(ParserInterface::class);
}
public function onRpcConnect(Server $server, int $fd, int $reactorId)
{
$args = func_get_args();
$this->runInSandbox(function (Event $event, Dispatcher $dispatcher) use ($fd, $server, $args) {
$event->trigger("swoole.rpc.Connect", $args);
}, $fd, true);
}
public function onRpcReceive(Server $server, $fd, $reactorId, $data)
{
$data = rtrim($data, ParserInterface::EOF);
$this->runInSandbox(function (Dispatcher $dispatcher) use ($fd, $data, $server) {
$dispatcher->dispatch($fd, $data);
}, $fd, true);
}
public function onRpcClose(Server $server, int $fd, int $reactorId)
{
$args = func_get_args();
$this->runInSandbox(function (Event $event) use ($args) {
$event->trigger("swoole.rpc.Close", $args);
}, $fd);
}
}