public function onStart() { parent::onStart(); if ($this->server->worker_id === 0 && in_array($this->server->setting['dispatch_mode'], [1, 3])) { # 如果 dispatch_mode 是 1, 3 模式, 开启定期清理数据 swoole_timer_tick(1000 * 60, function () { foreach (Host::$table as $key => $item) { $info = $this->server->connection_info($item['fd'], $item['from_id']); if ($item['removed']) { if ($info) { $this->server->close($item['fd'], $item['from_id']); } # 移除内存数据 Host::$table->del($key); } elseif (false === $info) { # 连接已经关闭 Host::$table->del($key); # 推送服务器 RPC::factory($item['fd'], $item['from_id'])->trigger('server.remove', $item->group, $item->id); Server::$instance->debug("remove closed client#{$item['group']}.{$item['id']}: {$item['ip']}:{$item['port']}"); } } }); } else { swoole_timer_tick(1000 * 60, function () { # 清理移除掉的 server $time = time(); foreach (Host::$table as $key => $item) { if ($item['removed'] && $item['removed'] - $time > 10) { # 清理数据 Host::$table->del($key); } } }); } }
/** * 连接一个RPC服务器 * * @param $ip * @param $port * @return bool */ public function connect($ip, $port) { if ($this->__client) { @$this->__client->close(); $this->__client = null; } /** * @var RPC $rpc */ $this->__ip = $ip; $this->__port = $port; $this->__closeByServer = false; $rpc = $this->__rpc; $key = $rpc::_getRpcKey(); $client = new \Swoole\Client(SWOOLE_TCP, SWOOLE_SOCK_ASYNC); $client->on('receive', function ($client, $data) use($key) { $arr = explode(Server::$EOF, $data); foreach ($arr as $item) { if ($item === '') { continue; } $tmp = @msgpack_unpack($item); if ($key) { $tmp = Server::decryption($tmp, $key); if (!$tmp) { \MyQEE\Server\Server::$instance->warn('rpc decryption data fail. data: ' . $item); continue; } } switch ($tmp->type) { case 'on': $event = $tmp->event; if (isset($this->__events[$event])) { # 回调执行 call_user_func_array($this->__events[$event], $tmp->args); } else { \MyQEE\Server\Server::$instance->warn("unknown rpc {$this->__rpc} event: {$event}"); } break; case 'close': $this->__closeByServer = true; $this->__client = null; break; default: \MyQEE\Server\Server::$instance->warn("unknown rpc type {$tmp->type}"); break; } } }); $client->on('connect', function ($client) { if (isset($this->__events['connect'])) { # 回调自定义的事件 call_user_func($this->__events['connect'], $client); } }); $client->on('close', function ($client) { $this->__client = null; \MyQEE\Server\Server::$instance->warn("rpc connection closed, {$this->__ip}:{$this->__port}."); if (!$this->isClosedByServer()) { # 不是被服务器强制关闭的则自动重新连接 $this->reconnect(); } if (isset($this->__events['close'])) { # 回调自定义的事件 call_user_func($this->__events['close'], $client); } }); $client->on('error', function ($client) { $this->__client = null; \MyQEE\Server\Server::$instance->warn("rpc connection({$this->__ip}:{$this->__port}) error: " . socket_strerror($client->errCode)); # 遇到错误则自动重连 swoole_timer_after(3000, function () { $this->reconnect(); }); if (isset($this->__events['error'])) { # 回调自定义的事件 call_user_func($this->__events['error'], $client); } }); $this->__client = $client; # 发心跳包 swoole_timer_tick(1000 * 60 * 5, function () { if ($this->__client && $this->__client->isConnected()) { $this->__client->send("" . Server::$EOF); } }); $this->__client->connect($ip, $port); return true; }
protected function callbackByString($str, $rs = false) { if ($obj = @msgpack_unpack($str)) { unset($str); if ($this->key) { $obj = \MyQEE\Server\RPC\Server::decryption($obj, $this->key); } if (!$obj) { Server::$instance->warn('decryption task result data error'); } if ($rs) { return $obj; } else { $this->callbackFinish($obj->id, $obj->data, $obj->wname); } } return null; }
public function onReceive($server, $fd, $fromId, $data) { /** * @var \Swoole\Server $server */ $tmp = @msgpack_unpack($data); if ($tmp && is_object($tmp)) { $data = $tmp; unset($tmp); if ($data instanceof \stdClass) { if ($data->bind) { # 绑定进程ID $server->bind($fd, $data->id); return; } if ($key = \MyQEE\Server\Register\Client::$host->key) { # 需要解密 $data = \MyQEE\Server\RPC\Server::decryption($data, $key); # 解密失败 if (!$data) { return; } } $eof = \MyQEE\Server\RPC\Server::$EOF; switch ($data->type) { case 'task': case 'taskWait': $rs = Server::$workerTask->onTask($server, $data->id, $data->wid, $data->data, $data->sid); if ($rs !== null || $data->type === 'taskWait') { # 执行 Finish $rsData = new \stdClass(); $rsData->id = $data->id; $rsData->data = $rs; $rsData->wname = $data->wname; if ($key) { # 加密数据 $rsData = \MyQEE\Server\RPC\Server::encrypt($rsData, $key) . $eof; } else { # 格式化数据 $rsData = msgpack_pack($rsData) . $eof; } $server->send($fd, $rsData, $fromId); } break; } } } else { Server::$instance->warn("task server get error msgpack data length: " . strlen($data)); Server::$instance->debug($data); $this->server->close($fd); } }