RPC(Remote Procedure Call Protocol)——遠(yuǎn)程過(guò)程調(diào)用協(xié)議敛苇,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù)梳码,而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議斜筐。RPC協(xié)議假定某些傳輸協(xié)議的存在冰啃,如TCP或UDP邓夕,為通信程序之間攜帶信息數(shù)據(jù)。在OSI網(wǎng)絡(luò)通信模型中阎毅,RPC跨越了傳輸層和應(yīng)用層焚刚。RPC使得開(kāi)發(fā)包括網(wǎng)絡(luò)分布式多程序在內(nèi)的應(yīng)用程序更加容易。
一直以來(lái)扇调,我們都是采用Restfull的方式矿咕。
今天讓我們來(lái)認(rèn)識(shí)一種更高效的調(diào)用協(xié)議——RPC
PHP的RPC框架并不少,比如鳥(niǎo)叔的Yar狼钮,比如我們今天講到的Hprose碳柱。
鳥(niǎo)叔的Yar只支持PHP,而Hprose提供了多種客戶端熬芜。
這就為我們搭建一個(gè)跨語(yǔ)言的服務(wù)提供了可能莲镣。
另外一個(gè)很重要的是原因是Hprose不止可以搭建基于HTTP協(xié)議的RPC服務(wù),還可以搭建基于Socket協(xié)議的RPC服務(wù)涎拉!
眾所周知瑞侮,HTTP協(xié)議是應(yīng)用層協(xié)議,而HTTP是基于Socket的曼库。這就意味著更高效的RPC服務(wù)区岗。
好了,廢話不多說(shuō)毁枯,現(xiàn)在我們直接來(lái)看Hprose官方給出的demo慈缔。
Server
<?php
require_once('Hprose.php');
function hello($name) {
return 'Hello ' . $name;
}
$server = new HproseHttpServer();
$server->addFunction('hello');
$server->start();
Client
<?php
require_once("Hprose.php");
$client = new HproseHttpClient('http://127.0.0.1/server.php');
echo $client->hello('World');
RPC,遠(yuǎn)程過(guò)程調(diào)用協(xié)議
何為遠(yuǎn)程過(guò)程調(diào)用協(xié)議种玛,通過(guò)這個(gè)demo就可以很輕松的理解了藐鹤。
簡(jiǎn)單來(lái)說(shuō)瓤檐,就是通過(guò)RPC,你可以將你的一個(gè)方法發(fā)布出去對(duì)外提供服務(wù)娱节。
而對(duì)于客戶端來(lái)說(shuō)挠蛉,這就是一個(gè)方法,客戶端可以像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程的方法肄满。
是不是很酷谴古!
那么我們?cè)撊绾螌PC集成到Y(jié)af中呢?
最理想的方式是將RPC服務(wù)封裝成一個(gè)類稠歉,在我們的控制器里繼承這個(gè)類就可以將我們的這個(gè)控制器變成一個(gè)RPC服務(wù)掰担。
那么該如何來(lái)實(shí)現(xiàn)呢?
直接來(lái)看代碼
<?php
/**
* Created by PhpStorm.
* User: yanbo
* Date: 16/4/7
* Time: 下午1:21
*/
class TestController extends Rpc
{
public function test()
{
return 'This is a rpc function.';
}
}
<?php
/**
* @author yanbo
* @desc 基礎(chǔ)控制器
*/
class Rpc extends Yaf_Controller_Abstract {
use Trait_Hprose;
public function init() {
$this->initRpc();
}
可以看到怒炸,Rpc類就是我們的Base類带饱。只不過(guò)在init方法中初始化了RPC服務(wù)。
這里有兩個(gè)坑阅羹,一個(gè)是PHP不支持多重繼承勺疼,一個(gè)是Yaf框架的控制器必須繼承Yaf_Controller_Abstract。
所以捏鱼,這里只能采用Trait的方式繼承Hprose执庐,然后在Rpc的構(gòu)造函數(shù)中初始化Hprose。
小知識(shí):Trait 是 PHP5.4 中的新特性,是 PHP 多重繼承的一種解決方案穷躁。
最后給大家來(lái)看下Hprose類
<?php
/**
* Created by PhpStorm.
* User: yanbo
* Date: 16/4/7
* Time: 下午1:32
*/
Trait Trait_Hprose
{
protected $allowMethodList = '';
protected $crossDomain = false;
protected $P3P = false;
protected $get = true;
protected $debug = false;
/**
* 架構(gòu)函數(shù)
* @access public
*/
public function initRpc() {
//控制器初始化
if(method_exists($this,'_initialize'))
$this->_initialize();
//導(dǎo)入類庫(kù)
Yaf_Loader::import('Rpc/Hprose.php');
//實(shí)例化HproseHttpServer
$server = new \HproseHttpServer();
if($this->allowMethodList){
$methods = $this->allowMethodList;
}else{
$methods = get_class_methods($this);
$methods = array_diff($methods, array('__construct','__call','_initialize', '__destruct', 'init', 'indexAction'));
}
$server->addMethods($methods,$this);
if($this->debug) {
$server->setDebugEnabled(true);
}
// Hprose設(shè)置
$server->setCrossDomainEnabled($this->crossDomain);
$server->setP3PEnabled($this->P3P);
$server->setGetEnabled($this->get);
// 啟動(dòng)server
$server->start();
exit;
}
/**
* 魔術(shù)方法 有不存在的操作的時(shí)候執(zhí)行
* @access public
* @param string $method 方法名
* @param array $args 參數(shù)
* @return mixed
*/
public function __call($method,$args){}
}
這個(gè)類里的代碼其實(shí)大部分都是抄TP的耕肩,天下代碼一大抄嘛。
哈哈哈~
后記
雖然實(shí)現(xiàn)了最初的目標(biāo)问潭,但是由于Yaf的特性,必須繼承Yaf_Controller_Abstract婚被。所以get_class_methods的時(shí)候會(huì)把Yaf_Controller_Abstract中的方法也變成RPC服務(wù)狡忙,這是唯一的一個(gè)缺憾。址芯。灾茁。
---
我是閆大伯,一只求知欲旺盛的程序猿