/** * 并发请求 * @param float $timeout * @return int */ function wait($timeout = 0.5) { if ($this->haveSwoole) { return $this->recvWaitWithSwoole($timeout); } elseif ($this->haveSockets) { return $this->recvWaitWithSockets($timeout); } $st = microtime(true); $t_sec = (int) $timeout; $t_usec = (int) (($timeout - $t_sec) * 1000 * 1000); $buffer = $header = array(); $success_num = 0; while (true) { $write = $error = $read = array(); if (empty($this->waitList)) { break; } foreach ($this->waitList as $obj) { if ($obj->socket !== null) { $read[] = $obj->socket->getSocket(); } } if (empty($read)) { break; } $n = stream_select($read, $write, $error, $t_sec, $t_usec); if ($n > 0) { //可读 foreach ($read as $sock) { $id = (int) $sock; /** * @var $retObj SOA_Result */ $retObj = $this->waitList[$id]; $data = $retObj->socket->recv(); //socket被关闭了 if (empty($data)) { $retObj->code = SOA_Result::ERR_CLOSED; unset($this->waitList[$id], $retObj->socket); continue; } //一个新的请求,缓存区中没有数据 if (!isset($buffer[$id])) { //这里仅使用了length和type,uid,serid未使用 $header[$id] = unpack(RPCServer::HEADER_STRUCT, substr($data, 0, RPCServer::HEADER_SIZE)); //错误的包头 if ($header[$id] === false or $header[$id]['length'] <= 0) { $retObj->code = SOA_Result::ERR_HEADER; unset($this->waitList[$id]); continue; } elseif ($header[$id]['length'] > $this->packet_maxlen) { $retObj->code = SOA_Result::ERR_TOOBIG; unset($this->waitList[$id]); continue; } $buffer[$id] = substr($data, RPCServer::HEADER_SIZE); } else { $buffer[$id] .= $data; } //达到规定的长度 if (strlen($buffer[$id]) == $header[$id]['length']) { //请求串号与响应串号不一致 if ($retObj->requestId != $header[$id]['serid']) { trigger_error(__CLASS__ . " requestId[{$retObj->requestId}]!=responseId[{$header['serid']}]", E_USER_WARNING); continue; } //成功处理 $this->finish(RPCServer::decode($buffer[$id], $header[$id]['type']), $retObj); $success_num++; } //继续等待数据 } } //发生超时 if (microtime(true) - $st > $timeout) { foreach ($this->waitList as $obj) { //TODO 如果请求超时了,需要上报服务器负载 $obj->code = $obj->socket->connected ? SOA_Result::ERR_TIMEOUT : SOA_Result::ERR_CONNECT; //执行after钩子函数 $this->afterRequest($obj); } //清空当前列表 $this->waitList = array(); return $success_num; } } //未发生任何超时 $this->waitList = array(); $this->requestIndex = 0; return $success_num; }
<?php define('DEBUG', 'on'); define('WEBPATH', realpath(__DIR__ . '/../')); require dirname(__DIR__) . '/libs/lib_config.php'; use Swoole\Protocol\RPCServer; //设置PID文件的存储路径 Swoole\Network\Server::setPidFile(__DIR__ . '/app_server.pid'); /** * 显示Usage界面 * php app_server.php start|stop|reload */ Swoole\Network\Server::start(function () { $AppSvr = new RPCServer(); $AppSvr->setLogger(new \Swoole\Log\EchoLog(true)); //Logger /** * 注册一个自定义的命名空间到SOA服务器 * 默认使用 apps/classes */ $AppSvr->addNameSpace('BL', __DIR__ . '/class'); /** * IP白名单设置 */ $AppSvr->addAllowIP('127.0.0.1'); $AppSvr->addAllowIP('127.0.0.2'); /** * 设置用户名密码 */ $AppSvr->addAllowUser('chelun', 'chelun@123456'); Swoole\Error::$echo_html = false;