dubbo-php-framework的服务注册zookeeper过程解析(一)

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

我们在分析BaseServer的onManagerStart回调函数时,看到有调用Provider注册到zookeeper的过程,这篇我们详细解析下这个过程。

//app启动后向zookeeper注册服务信息
FSOFRegistry::instance()->setParams($this->processName, $this->config, $this->port,
            $this->serverProviders, $this->start_without_registry);
FSOFRegistry::instance()->registerZk();
//注册单列类
class FSOFRegistry 
{
	//设置zookeeper的日志文件及日志级别(1.error; 2.warn; 3.info; 4.debug)
	const ZOOKEEPER_LOG_NO = 0;
	const ZOOKEEPER_LOG_ERROR = 1;
	const ZOOKEEPER_LOG_WARN = 2;
	const ZOOKEEPER_LOG_INFO = 3;
	const ZOOKEEPER_LOG_DEBUG = 4;

	protected $appName;//应用名称
	protected $port;//应用监听端口信息
	protected $config;//配置信息
	protected $serverProviders;//服务接口信息
	protected $localIp = '127.0.0.1';
	protected $ephemeral = false;

	//zookeeper相关
	protected $zkService = null;//zk service
	protected $fsofUrlList = array();//要注册到zk的信息的列表
    
	protected $start_without_registry;//p2p模式

	private static $_instance;//本实例信息,这里使用了单列模式

        private $logger;//日志组件

        //单列模式创建实例
	public static function instance()
	{
		if (empty(FSOFRegistry::$_instance))
		{
			FSOFRegistry::$_instance = new FSOFRegistry();
		}
		return FSOFRegistry::$_instance;
	}
	
	public function __construct()
	{
            $this->logger = \Logger::getLogger(__CLASS__);//初始化日志组件
	}

    //BaseServer侧调用这个函数设置相关属性信息,这里属性数据已经在类的初始化处解释过,这里不重复解释。
	public function setParams($appName, $appConfig, $port, $serverProviders, $registry = true)
	{
            $this->logger->info("serverProviders:".json_encode($serverProviders));
		$this->appName = $appName;
		$this->port = $port;
		$this->config = $appConfig;
		$this->serverProviders = $serverProviders;
		$this->start_without_registry = $registry;

		try
		{   
                         //获取Provider服务所在的机器
			$this->localIp = FSOFSystemUtil::getServiceIP();
		}
		catch (\Exception $e)
		{
            $this->logger->error('The server network configuration errors',$e);
			//当获取IP失败时,禁止往zk注册
			$this->start_without_registry = true;
		}
	}
//注册到zookeeper
public function registerZk()
	{
		if(!$this->start_without_registry)//非p2p模式,服务启动时,需要注册流程
		{
			try
			{
                $this->logger->info("init zk start...");
				
				$this->ServiceSerialize();//生成service urls
				$this->createZookeeperService();//创建zk service
				$this->setZkLog();//设置日志组件信息

				if (!$this->ephemeral)//这个参数按意思是标记是否是短暂注册,但全篇都是false。
				{
					//静态注册模式
					$this->registerServiceToZk();//调用zk的接口,注册到zk
					$this->inventZkService();//注销zk服务
				}

				//连接成功后,通过注入watcherCallFunc函数进行注册
                $this->logger->info("init zk end...");
			}
			catch (\Exception $e)
			{
                $this->logger->error($e->getMessage(),$e);
			}
		}
	}
//生成要注册到zk的服务信息
protected function ServiceSerialize()
	{
		try 
		{
			unset($this->fsofUrlList);//清理信息
			if (!empty($this->serverProviders))//服务信息不为空
			{
				if ($this->ephemeral)//短暂的
				{
					//注册时间
					//$this->config["service_properties"]["timestamp"] = (int)(microtime(true) * 1000);
					$this->config["service_properties"]["dynamic"] = "true";
				} 
				else//长久的,按逻辑,流程会走这里。 
				{
					$this->config["service_properties"]["dynamic"] = "false";
				}

				$services = $this->serverProviders;
				foreach ($services as $interface => $serviceInfo)
				{
					//合并全局配置
					if (isset($this->config["service_properties"]))
					{
						//接口配置优先级高于全局配置,所以$serviceInfo放后面
						$serviceInfo = array_merge($this->config["service_properties"], $serviceInfo);
					}

					//不用上报的信息去掉
					unset($serviceInfo['service']);
					unset($serviceInfo['p2p_mode']);

					if (empty($serviceInfo["version"]))
					{
						$serviceInfo['version'] = FSOFConstants::FSOF_SERVICE_VERSION_DEFAULT;
					}
					
					//与dubbo兼容处理
					$serviceInfo['interface'] = $interface;//dubbo_admin需要使用
                    //序列化方式
                    $serviceInfo['serialization']= "fastjson";

					ksort($serviceInfo);//参数排序,与dubbo兼容
					
                    //要注册到zk的url信息组成部分
					$urlPara = array(
						'scheme' => 'dubbo',
						'host' => $this->localIp,
						'port' => $this->port,
						'path' => '/' . $interface,
						//http_build_query会进行urlencode导致query参数被多编码一次,使用urldecode抵消
						'query' => urldecode(http_build_query($serviceInfo)),
					);
                    $this->logger->debug("serviceInfo:" . json_encode($serviceInfo) . "|urlPara:" . json_encode($urlPara));
					try
					{
						$fsofUrl = new FSOFUrl($urlPara);//按规则拼接dubbo的url协议
					}
					catch (\Exception $e)
					{
                        $this->logger->error('init url failed|app:' . $this->appName . '|urlPara:' . json_encode($urlPara));
					}
                     
					$this->fsofUrlList[] = $fsofUrl;
				}
			}
		}
		catch(\Exception $e)
		{
			$errMsg = $e->getMessage();
            $this->logger->error('ServiceSerialize:'.$errMsg, $e);
		}
	}

猜你喜欢

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