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

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

我们接着前面的文章继续分析,先从完整的接到请求后的处理过程开始。

//接收到完整的数据包后的处理过程
public function onOneRequest($client_id, $request)
	{

		if($this->parser->isHearBeatRequest($request))
		{
			//心跳请求,不需要数据回送
		}
		else if($this->parser->isNormalRequest($request) || $this->parser->isOneWayRequest($request))
		{
			//获取配置信息
			$appConfig = $this->getAppConfig();
			
			//Number of packet loss in a row
			$lossNumber = $appConfig['fsof_setting']['loss_number'];
			
			//判断是否开启过载丢包模式
			$restOfLostNum = $this->server->getOverloadMonitor()->getLossNum();
			if($restOfLostNum > 0)
			{
				// 加入对过载丢失数据的统计
				$this->server->getAppMonitor()->onRequest($request);
				
				//回复客户端
				if($restOfLostNum >= $lossNumber)
				{
					if($this->swoole_server->exist($client_id))
					{
						$result = 'provider连续过载, 开启丢消息模式';
						$this->packResponse($client_id, $request, $result, false, true);
					}
				}
				else
				{
					if($this->swoole_server->exist($client_id))
					{
						$result = 'provider开启丢消息模式, 连续丢包中...';
						$this->packResponse($client_id, $request, $result, false, true);
					}
				}
				
				//递减丢包数量
				$this->server->getOverloadMonitor()->lossNumDecr();

				//监控请求错误处理数量
				$this->server->getAppMonitor()->onError($request);
			}
			else
			{
				$this->requestProcessor($client_id,$request);
			}
		}
		else
		{
            $this->logger->error("invalid request = $request");
		}
	}
//发送回复包
public function packResponse($client_id, $request, $data, $businessError,$frameError)
{
    $response = new DubboResponse();//声明response对象
	$response->setSn($request->getSn());//设置response的sn属性,这个属性用于追踪一个完整的请求流程

    if($frameError){//如果是框架报错
        $response->setStatus(DubboResponse::SERVICE_ERROR);//设置response的状态信息
        $response->setErrorMsg($data);//设置response的错误信息
    }

    if($businessError){//如果是业务报错
        $response->setErrorMsg($data);//设置response的错误信息
    }

    $response->setResult($data);//设置回复包的数据信息
	$this->sendResponse($response, $client_id);//向该clientid发送回复包response

	return $response;
}
public function sendResponse(DubboResponse $response, $client_id)
    {
        try
		{
            $send_data = $this->parser->packResponse($response);//调用解析器编码回复包
            $send_len = strlen($send_data);//计算数据长度信息
    
            //默认所有server的response最大5M,每个分包允许重发2次,预计最多10次循环,防止网络出错导致server直接挂死在循环中
            $cnt = (($send_len / DubboParser::RESPONSE_TCP_SEGMENT_LEN) + 1) * 2;
            $tmp_len = $send_len;
            for ($i = 0; $i < $cnt; $i++)
			{
                if ($tmp_len > DubboParser::RESPONSE_TCP_SEGMENT_LEN)
				{
                    //大于1M 分段发送
                    $tmp_data = substr($send_data, 0, DubboParser::RESPONSE_TCP_SEGMENT_LEN);
                    //调用swoole的api来发送数据,该数据是回复给clientid的客户端
                    if ($this->swoole_server->send($client_id, $tmp_data))
					{
                        $tmp_len -= DubboParser::RESPONSE_TCP_SEGMENT_LEN;
                        $send_data = substr($send_data, DubboParser::RESPONSE_TCP_SEGMENT_LEN);
                    }
					else
					{
                        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
                        {
                            $last_error_no = $this->swoole_server->errno();
                        }
                        else
                        {
                            $last_error_no = swoole_errno();
                        }
                        if (0 == $last_error_no)
						{
                            //表示该连接己关闭
                            $this->logger->error("当前连接己关闭,发送失败");
                            break;
                        }
						else
						{
                            $this->logger->error('send response split package fail one time!');
                        }
                    }
                    $this->logger->warn('the length of response: '.$send_len.'; send split package '.$i.'/'.$cnt);
                }
				else
				{
                    //小于1M一次性发完
                    if ($this->swoole_server->send($client_id, $send_data))
					{
                        break;
                    }
					else
					{
                        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
                        {
                            $last_error_no = $this->swoole_server->errno();
                        }
                        else
                        {
                            $last_error_no = swoole_errno();
                        }
                        if (0 == $last_error_no)
						{
                            //表示该连接己关闭
                            $this->logger->error("当前连接己关闭,发送失败");
                            break;
                        }
						else
						{
                            $this->logger->error('send response last package fail one time!');
                        }
                    }
                }
            }
        }
		catch (\Exception $e)
		{
            $this->logger->error($e->getMessage(), $e);
        }

        return $send_len;
    }

猜你喜欢

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