dubbo-php-framework的Protocol解析(四)

版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/82730899

接着上面一篇我们分析正常请求的处理过程。

private function requestProcessor($client_id, $request)
	{
		//开始执行时间
		$request->startTime = microtime(true);
		//监控请求数量
		$this->server->getAppMonitor()->onRequest($request);

		//设置traceContext, 增加本地的IP地址及APP的端口
		$appConfig = $this->getAppConfig();
		$localIP = FSOFSystemUtil::getLocalIP();
		$appPort = $appConfig['server']['listen'][0];

		$params = $request->__toString();
		if (mb_strlen($params, 'UTF-8') >= 512)
		{
			$params = mb_substr($params, 0, 512, 'UTF-8').' ...';
		}
        $this->logger->debug("in|".$params);

        $businessError = false;
        $frameError = false;
		$result = null;
		//业务处理状态
		$requestFlag = false;
		//返回给客户端执行结果信息
		//$errMsg = 'ok';		//异常信息

		//消息在队列等待时间
		$wait_InQueueTime = 0;
		$inQueueTime = DubboParser::getReqInQueueTime($request);
		if($inQueueTime)
		{
			$wait_InQueueTime = round(microtime(true)*1000000) - $inQueueTime;
		}

		//处理前先检测连接是否仍正常,如己断开则不进行处理
		if(!$this->swoole_server->exist($client_id))
		{
			//执行结束时间
			$request->endTime = microtime(true);
			$cost_time = (int)(($request->endTime - $request->startTime)* 1000000);
			goto END_TCP_CLOSE;
		}
        //检测服务状态信息,这里主要检查是否过载
		$status = $this->checkSwooleStatus($request, $localIP, $appPort);
		if(self::FSOF_SWOOLE_STATUS_OK == $status)//服务正常,也就是没过载
		{
            //当前app是否提供了满足条件的服务
			if($this->server->serviceExist($request->getService(),  $request->getGroup(), $request->getVersion()))
			{   
                //获取app中满足条件的服务实例,一个app提供的所有服务都以单实例的形式存于内存中
				$serviceInstance = $this->server->getServiceInstance($request->getService(), $request->getGroup(), $request->getVersion());
				if (null != $serviceInstance)
				{
					try
					{
                        //调用PHP的反射接口反射服务实例
						$serviceReflection = new \ReflectionObject($serviceInstance);
                        //判断服务实例中是否存在请求的方法
						if ($serviceReflection->hasMethod($request->getMethod()))
						{
                            //获取方法对象
							$method = $serviceReflection->getmethod($request->getMethod());
							//允许invoke protected方法
							$method->setAccessible(true);
                            //获取请求方法参数信息
                            $params = $request->getParams();
                            if($params == NULL)//如果没有参数信息,转成空数组,这里应该是为了业务处理统一。
                            {
                                $params = array();
                            }
                            //执行反射回调
							$result = $method->invokeArgs($serviceInstance, $params);
							$requestFlag = true;
						}
						else//服务实例不存在请求方法信息,抛出业务报错。
						{
                            $businessError = true;
							$result = 'function not found:'.$request->getMethod().' in '.$request->getService();
                            $this->logger->error("[{$request->getMethod()}] function not found:".$request->getService());
						}
					}
					catch (\Exception $e)//捕捉执行过程中的所有异常,记录为框架异常。
					{
                        $this->logger->error($e);
                        $frameError = true;
                        $result = $e->getMessage().' in '.$e->getFile().'|'.$e->getLine();
					}

					//如果provider service有状态,则$serviceInstance用完后unset,下次请求重新new, 防止内存泄漏; 对于无状态的service,AppContext会复用$serviceInstance
					if (!$this->server->isStateless())
					{
						unset($serviceInstance);
					}

					unset($method);
					unset($serviceReflection);
				}
				else//反射服务实例失败,记录为框架错误。
				{
                    $frameError = true;
					$result ='get instance failed! | '.$request->getService();
                    $this->logger->error(json_encode($result));
				}
			}
			else//服务实例不存在,记录为框架错误。
			{
                $frameError = true;
				$result = 'service not found:'.$request->getGroup()."/".$request->getService().":".$request->getVersion();
                $this->logger->error(json_encode($result));
			}
		}
		else //服务实例过载
		{
            $frameError = true;
			$result = 'provider过载, 请求消息在队列等待时间超过阀值';
		}

		$request->endTime = microtime(true);//执行结束时间
		$cost_time = (int)(($request->endTime - $request->startTime)* 1000000);
				
        //判断swoole是否还保持着这个客服端连接
		if($this->swoole_server->exist($client_id))
		{
			//发送response
			$response = $this->packResponse($client_id, $request, $result, $businessError,$frameError);
			$msg = $response->__toString();
			if (mb_strlen($msg, 'UTF-8') >= 512)
			{
				$msg = mb_substr($msg, 0, 512, 'UTF-8').' ...('.strlen($msg).')';
			}

            $this->logger->debug(sprintf("out|%s|invokeCostTime:%dus|waitInQueueTime:%dus", $msg, $cost_time, $wait_InQueueTime));
		}
		else //swoole已经不保持这个链接,这时候只是记录日志,已经没法给客户端回复错误信息了。
		{
			END_TCP_CLOSE:
			$errMsg = "socket closed by consumer, provider discard response data";
            $this->logger->error("out|{$errMsg}|invokeCostTime:{$cost_time}us| waitInQueueTime:{$wait_InQueueTime}us");
			$requestFlag = false;
		}

		if($requestFlag)
		{
			//监控请求正常处理数量
			$this->server->getAppMonitor()->onResponse($request);
		}
		else
		{
			//监控请求错误处理数量
			$this->server->getAppMonitor()->onError($request);
		}
	}
//服务实例上下文管理
final class AppContext
{
    private $instances = array();

    private $stateless = FALSE;//默认所有服务都是有状态的,每次使用都重新new
    
    private $server;
    
    public function setStateless($stateless, $server)
    {
    	$this->stateless = $stateless;
    	$this->server = $server;	
    }
    
    public function isStateless()
    {
        return $this->stateless;
    }
    
    public function getInstance($className, $params = null)
    {
		if($this->stateless) //服务是有状态的,除了首次new之外,其他的都通过内存缓存,后续不再重复new。
		{
            \Logger::getLogger(__CLASS__)->debug("get stateless instance for $className");
	        if (isset($this->instances[$className])) 
	        {
	            return $this->instances[$className];
	        }
	        
	        if (!class_exists($className,true)) 
	        {
	            throw new \Exception("no class {$className}");
	        }
	        
	        if (empty($params)) 
	        {
	            $this->instances[$className] = new $className();
	        } 
	        else 
	        {
	            $this->instances[$className] = new $className($params);
	        }
	        
	        return $this->instances[$className];
        }
        else //服务实例是无状态的,每次都是直接new新的服务实例
        {
            \Logger::getLogger(__CLASS__)->debug("get new instance for $className");
        	if (!class_exists($className,true)) 
	        {
	            throw new \Exception("no class {$className}");
	        }
	        
        	if (empty($params)) 
	        {
	            return new $className();
	        } 
	        else 
	        {
	            return new $className($params);
	        } 
	    }
    }
}

猜你喜欢

转载自blog.csdn.net/u013702678/article/details/82730899
今日推荐