dubbo-php-framework的客戶端api解析(一)
阿新 • • 發佈:2018-12-11
從這篇,我們開始分析客戶端的側的流程,所謂客戶端就是指dubbo-php-frame框架中consumer端,我們結合demo來看看consumer的呼叫流程,下面程式碼路徑為dubbo-php-framework-master/demo/demo-consumer/server/Consumer.php
<?php $APP_SRC_PATH = __DIR__; $fsofApiPath = dirname(dirname(dirname($APP_SRC_PATH))).DIRECTORY_SEPARATOR.'api'.DIRECTORY_SEPARATOR.'FSOFApi.php'; require_once($fsofApiPath);//載入api檔案,檔案路徑為dubbo-php-framework-master/api/FSOFApi.php FSOFApi::configure('demo-consumer', $APP_SRC_PATH);//FSOFApi的初始化,傳入的引數為app名字和consumer端目錄 require_once('log4php/Logger.php'); Logger::configure(dirname(dirname(__FILE__)).'/config/log4php.xml'); date_default_timezone_set('PRC'); //php框架呼叫php提供的服務 $service = 'com.fenqile.example.DemoService'; $proxy = FSOFApi::newProxy($service, 3); $ret = $proxy->invoke("sayHello","zhangsan"); echo "ret:$ret".PHP_EOL;
從這個程式碼可以看出,核心呼叫邏輯是在FSOFApi::newProxy和proxy的invoke中完成的,我們就從FSOFApi類開始解析。
class FSOFApi { private static $__FSOF_CONSUMER_APP_NAME__ = NULL; private static $__FSOF_CONSUMER_APP_SRC_PATH__ = NULL; /** * 設定Consumer執行上下文環境,在使用fsof_consumer時,該函式要最先呼叫 * @param $appName consumer app的名字 * @param $appSrcPath consumer app src原始碼的絕對路徑 */ public static function configure($appName, $appSrcPath) { self::$__FSOF_CONSUMER_APP_NAME__ = $appName; self::$__FSOF_CONSUMER_APP_SRC_PATH__ = $appSrcPath; } /** * * 獲取指定provider服務的proxy物件 * @param $service service配置檔案中的key 例:com.alibaba.test.TestService 必選 * @param int $ioTimeout 連線超時時間和接收資料超時時間 單位 s;支援小數0.5 500ms * @return \com\fenqile\fsof\consumer\proxy\Proxy|null */ public static function newProxy($service ,$ioTimeout = 3) { $s = NULL; if(empty(self::$__FSOF_CONSUMER_APP_NAME__) || empty(self::$__FSOF_CONSUMER_APP_SRC_PATH__))//判斷引數有效性 { \Logger::getLogger(__CLASS__)->error("appName or appSrcPath not set,please use FSOFApi::configure() for set."); return null; } else { if(!is_numeric($ioTimeout) || $ioTimeout <= 0) //判斷超時時間設定,在分散式呼叫中,超時時間必須得有,防止介面超時引起的雪崩 { $ioTimeout = 3; } $consumerFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'consumer'.DIRECTORY_SEPARATOR.'FSOFConsumer.php'; //載入FSOFConsumer require_once($consumerFile); $app_setting = array('app_name' => self::$__FSOF_CONSUMER_APP_NAME__, 'app_src' => self::$__FSOF_CONSUMER_APP_SRC_PATH__); FSOFConsumer::init($app_setting);//初始化Consumer框架資訊,細節後續分析 $s = ProxyFactory::getInstance($service, $ioTimeout);//獲取Proxy例項資訊,細節後續分析 } return $s; } }
我們接著分析FSOFConsumer的init過程,這裡主要是完成了consumer端對於一些必須庫和檔案的載入,consumer端也有自己的配置,這裡也有配置檔案的解析。
class FSOFConsumer { /** * @var boolean Has [FSOFConsumer::init] been called? */ protected static $_init = FALSE; protected static $_initSetting; public static function init(array $settings = NULL) { if (self::isConsumerInit()) { // Do not allow execution twice return; } \Logger::getLogger(__CLASS__)->info("consumer cfg:".json_encode($settings, true)); $consumerRoot = __DIR__; $fsofBootPath = dirname($consumerRoot); //載入commom $fsofCommonPath = $fsofBootPath.DIRECTORY_SEPARATOR.'common'; require_once($fsofCommonPath.DIRECTORY_SEPARATOR.'BootStrap.php'); //載入registry $fsofRegistryPath = $fsofBootPath.DIRECTORY_SEPARATOR.'registry'; require_once($fsofRegistryPath.DIRECTORY_SEPARATOR.'BootStrap.php'); //檢查輸入引數app_src if ((!isset($settings['app_src'])) || (!isset($settings['app_name']))) { throw new \Exception("FSOFConsumer::init傳入的app的src路徑引數不準確"); } $consumerConfigFile = $settings['app_src']; $consumerConfigFile = rtrim($consumerConfigFile, DIRECTORY_SEPARATOR); $consumerConfigFile = $consumerConfigFile.DIRECTORY_SEPARATOR.'consumer'.DIRECTORY_SEPARATOR.$settings['app_name'].'.consumer'; if (file_exists($consumerConfigFile)) { try { $consumerConfig = parse_ini_file($consumerConfigFile, true); } catch (\Exception $e) { throw new \Exception("consumer配置檔案有誤[".$consumerConfigFile."]"); } } else { $consumerConfig = array(); } self::$_initSetting = $settings; //註冊consumer框架的autoLoader self::registerConsumerFrameAutoLoader($consumerRoot); //註冊consumer的動態代理工廠 ProxyFactory::setConsumerConfig($consumerConfig, $consumerConfigFile, $settings); // FSOFConsumer is now initialized self::$_init = TRUE; } private static function registerConsumerFrameAutoLoader($consumerRoot) { if (!self::isConsumerInit()) { //註冊框架頂層名稱空間到自動載入器 require_once $consumerRoot.DIRECTORY_SEPARATOR.'FrameAutoLoader.php'; FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer', $consumerRoot); FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\app', $consumerRoot.DIRECTORY_SEPARATOR.'app'); FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\fsof', $consumerRoot.DIRECTORY_SEPARATOR.'fsof'); FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\proxy', $consumerRoot.DIRECTORY_SEPARATOR.'proxy'); FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\client', $consumerRoot.DIRECTORY_SEPARATOR.'client'); spl_autoload_register(__NAMESPACE__.'\FrameAutoLoader::autoload'); } } public static function getInitSetting() { return self::$_initSetting; } public static function isConsumerInit() { return self::$_init; } }