/**
  * 获取一个实例
  * @return instance
  */
 protected function __instance()
 {
     if (\Thrift\Context::get('serverName') != $this->serviceName) {
         \Thrift\Context::put('serverName', $this->serviceName);
     }
     $address = CLientForTest::getOneAddress($this->serviceName);
     list($ip, $port) = explode(':', $address);
     $socket = new \Thrift\Transport\TSocket($ip, $port);
     // 接收超时
     if (($timeout = \Thrift\Context::get('timeout')) && $timeout >= 1) {
         $socket->setRecvTimeout($timeout * 1000);
     } else {
         // 默认30秒
         $socket->setRecvTimeout(30000);
     }
     $transport = new \Thrift\Transport\TFramedTransport($socket);
     $pname = \Thrift\Context::get('protocol') ? \Thrift\Context::get('protocol') : 'binary';
     $protocolName = self::getProtocol($pname);
     $protocol = new $protocolName($transport);
     $classname = '\\Provider\\' . $this->serviceName . "\\" . $this->serviceName . "Client";
     if (!class_exists($classname)) {
         $this->includeFile($classname);
     }
     try {
         $transport->open();
     } catch (\Exception $e) {
         CLientForTest::kickAddress($address);
         throw $e;
     }
     return new $classname($protocol);
 }
示例#2
0
 /**
  * 业务处理(non-PHPdoc)
  * @see PHPServerWorker::dealProcess()
  */
 public function dealProcess($recv_str)
 {
     // 拷贝一份数据包,用来记录日志
     $recv_str_copy = $recv_str;
     // 统计监控记录请求开始时间点,后面用来统计请求耗时
     StatisticHelper::tick();
     // 清除上下文信息
     \Thrift\Context::clear();
     // 服务名
     $serviceName = $this->serviceName;
     // 本地调用方法名
     $method_name = 'none';
     // 来源ip
     $source_ip = $this->getRemoteIp();
     // 尝试读取上下文信息
     try {
         // 去掉TFrameTransport头
         $body_str = substr($recv_str, 4);
         // 读上下文,并且把上下文数据从数据包中去掉
         \Thrift\ContextReader::read($body_str);
         // 再组合成TFrameTransport报文
         $recv_str = pack('N', strlen($body_str)) . $body_str;
         // 如果是心跳包
         if (\Thrift\Context::get('isHeartBeat') == 'true') {
             $thriftsocket = new \Thrift\Transport\TBufferSocket();
             $thriftsocket->setHandle($this->connections[$this->currentDealFd]);
             $thriftsocket->setBuffer($recv_str);
             $framedTrans = new \Thrift\Transport\TFramedTransport($thriftsocket);
             $protocol = new Thrift\Protocol\TBinaryProtocol($framedTrans, false, false);
             $protocol->writeMessageBegin('#$%Heartbeat', 2, 0);
             $protocol->writeMessageEnd();
             $protocol->getTransport()->flush();
             return;
         }
     } catch (Exception $e) {
         // 将异常信息发给客户端
         $this->writeExceptionToClient($method_name, $e, self::getProtocol(\Thrift\Context::get('protocol')));
         // 统计上报
         StatisticHelper::report($serviceName, $method_name, $source_ip, $e, $recv_str_copy);
         return;
     }
     // 客户端有传递超时参数
     if (($timeout = \Thrift\Context::get("timeout")) && $timeout >= 1) {
         pcntl_alarm($timeout);
     }
     // 客户端有传递服务名
     if (\Thrift\Context::get('serverName')) {
         $serviceName = \Thrift\Context::get('serverName');
     }
     // 尝试处理业务逻辑
     try {
         // 服务名为空
         if (!$serviceName) {
             throw new \Exception('Context[serverName] empty', 400);
         }
         // 如果handler命名空间为provider
         if ($this->handlerNamespace == 'Provider') {
             $handlerClass = $this->handlerNamespace . '\\' . $serviceName . '\\' . $serviceName . 'Handler';
         } else {
             $handlerClass = $this->handlerNamespace . '\\' . $serviceName;
         }
         // processor
         $processorClass = $this->providerNamespace . '\\' . $serviceName . '\\' . $serviceName . 'Processor';
         // 文件不存在尝试从磁盘上读取
         if (!class_exists($handlerClass, false)) {
             clearstatcache();
             if (!class_exists($processorClass, false)) {
                 require_once $this->providerDir . '/' . $serviceName . '/Types.php';
                 require_once $this->providerDir . '/' . $serviceName . '/' . $serviceName . '.php';
             }
             $handler_file = $this->handlerNamespace == 'Provider' ? $this->handlerDir . '/' . $serviceName . '/' . $serviceName . 'Handler.php' : $this->handlerDir . '/' . $serviceName . '.php';
             if (is_file($handler_file)) {
                 require_once $handler_file;
             }
             if (!class_exists($handlerClass)) {
                 throw new \Exception('Class ' . $handlerClass . ' not found', 404);
             }
         }
         // 运行thrift
         $handler = new $handlerClass();
         $processor = new $processorClass($handler);
         $pname = \Thrift\Context::get('protocol') ? \Thrift\Context::get('protocol') : 'binary';
         $protocolName = self::getProtocol($pname);
         $thriftsocket = new \Thrift\Transport\TBufferSocket();
         $thriftsocket->setHandle($this->connections[$this->currentDealFd]);
         $thriftsocket->setBuffer($recv_str);
         $framedTrans = new \Thrift\Transport\TFramedTransport($thriftsocket, true, true);
         $protocol = new $protocolName($framedTrans, false, false);
         $protocol->setTransport($framedTrans);
         // 请求开始时执行的函数,on_request_start一般在bootstrap初始化
         if (function_exists('on_phpserver_request_start')) {
             \on_phpserver_request_start();
         }
         $processor->process($protocol, $protocol);
         // 请求结束时执行的函数,on_request_start一般在bootstrap中初始化
         if (function_exists('on_phpserver_request_finish')) {
             // 这里一般是关闭数据库链接等操作
             \on_phpserver_request_finish();
         }
         $method_name = $protocol->fname;
     } catch (Exception $e) {
         // 异常信息返回给客户端
         $method_name = !empty($protocol->fname) ? $protocol->fname : 'none';
         $this->writeExceptionToClient($method_name, $e, !empty($protocolName) ? $protocolName : 'Thrift\\Protocol\\TBinaryProtocol');
         StatisticHelper::report($serviceName, $method_name, $source_ip, $e, $recv_str_copy);
         return;
     }
     // 统计上报
     StatisticHelper::report($serviceName, $method_name, $source_ip);
 }