PHP函数参考33-一次清楚RPC框架Yar
目录
Yar 是一个轻量级, 高效的RPC框架, 它提供了一种简单方法来让PHP项目之间可以互相远程调用对方的本地方法. 并且Yar也提供了并行调用的能力. 可以支持同时调用多个远程服务的方法。
yar的特点
-
快速,简单,简单
-
支持并发RPC调用
-
支持多种数据包(php, json, msgpack内置)
-
支持多种传输协议(http、https、TCP)
-
详细的调试信息
运行时配置
yar.timeout //default 5000 (ms)
yar.connect_timeout //default 1000 (ms)
yar.packager //default "php", when built with --enable-msgpack then default "msgpack", it should be one of "php", "json", "msgpack"
yar.debug //default Off
yar.expose_info // default On, whether output the API info for GET requests
yar.content_type // default "application/octet-stream"
yar.allow_persistent // default Off
server端
class Operator {
/**
* Add two operands
* @param interge
* @return interge
*/
public function add($a, $b) {
if(!$a || !$b){
throw new Exception("server exception:a | b不能为空.");
}
return $this->_add($a, $b);
}
/**
* Sub
*/
public function sub($a, $b) {
return $a - $b;
}
/**
* Mul
*/
public function mul($a, $b) {
return $a * $b;
}
/**
* 返回一个数组
* @return array
*/
public function returnArray(){
return ['a'=>"apple","b"=>'banana'];
}
/**
* Protected methods will not be exposed
* @param interge
* @return interge
*/
protected function _add($a, $b) {
return $a + $b;
}
}
$server = new Yar_Server(new Operator());
$server->handle();//启动服务, 开始接受客户端的调用请求. 来自客户端的调用, 都是通过POST请求发送过来的
假设server端脚本访问路径:http://demo.130.com/FunctionsReference/yar/yarServer.php
则访问时会展示:
-Operator::add($a, $b)
----------------------
/**
* Add two operands
* @param interge
* @return interge
*/
-Operator::sub($a, $b)
----------------------
/**
* Sub
*/
-Operator::mul($a, $b)
----------------------
/**
* Mul
*/
----------------------
-Operator::returnArray()
/**
* 返回一个数组
* @return array
*/
client端
//发起一个RPC调用, 并且得到返回值. 如果服务端的远程调用抛出异常, 那么本地也会相应的抛出一个Yar_Server_Exception异常.
$client = new yar_client("http://demo.130.com/FunctionsReference/yar/yarServer.php");
//设置调用远程服务的一些配置, 比如超时值, 打包类型等.
//可以是: YAR_OPT_PACKAGER、YAR_OPT_PERSISTENT (需要服务端支持keepalive)、YAR_OPT_TIMEOUT、YAR_OPT_CONNECT_TIMEOUT
//Set timeout to 1s
$client->SetOpt(YAR_OPT_CONNECT_TIMEOUT, 1000);
//Set packager to JSON
//$client->SetOpt(YAR_OPT_PACKAGER, "json");//默认php, "php", "json", "msgpack",this server accept json packager
//设置header
$client->SetOpt(YAR_OPT_HEADER, array("hd1: val", "hd2: val")); //Custom headers, Since 2.0.4
try{
/*远程调用方式1: call directly */
var_dump($client->add(1, 2));
/*远程调用方式2: call via __call */
var_dump($client->__call("add", array(3, 2)));
var_dump($client->returnArray());
var_dump($client->add(0, 2));//远端服务端抛出异常
} catch (Yar_Server_Exception $sex) {
//Yar_Server_Exceptioin可以捕获server端throw new exception异常
var_dump($sex->getMessage());
}catch(Yar_Client_Exception $cex){
//处理Yar_Client_Exception
var_dump($cex->getMessage());
}
/* public以外的方法不能被调用,so __add can not be called */
//var_dump($client->_add(1, 2));
输出:
int(3)
int(5)
array(2) {
["a"]=>
string(5) "apple"
["b"]=>
string(6) "banana"
}
string(37) "server exception:a | b不能为空."
并行调用
-
Yar_Concurrent_Client::call — 注册一个并行的服务调用
-
Yar_Concurrent_Client::loop — 发送所有注册的并行调用
public static Yar_Concurrent_Client::loop([ callable $callback[, callable $error_callback]] ) : boolean
如果这个回掉函数被设置, 那么Yar在发送出所有的请求之后立即调用一次这个回掉函数(此时还没有任何请求返回), 调用的时候$callinfo参数是NULL。
如果在注册并行调用的时候指定了callback, 那么那个callback有更高的优先级。
function callback($retval, $callinfo)
{
if ($callinfo == NULL) {
echo "现在, 所有的请求都发出去了, 还没有任何请求返回\n";
} else {
echo "这是一个远程调用的返回, 调用的服务名是", $callinfo["method"],
". 调用的sequence是 ", $callinfo["sequence"], "\n";
var_dump($retval);
}
}
function loopCallback($retval, $callinfo){
}
function error_callback($type, $error, $callinfo)
{
error_log($error);
}
$webserviceApi = "http://demo.130.com/FunctionsReference/yar/yarServer.php";
try{
Yar_Concurrent_Client::call($webserviceApi, "mul", [1,1], "callback");
// if the callback is not specificed, callback in loop will be used
Yar_Concurrent_Client::call($webserviceApi, "mul", [2,2]);
//it should be one of "php", "json", "msgpack" .默认php格式, json告诉服务端,客户端接收json格式数据
Yar_Concurrent_Client::call($webserviceApi, "addJson", [3,3], "callback", NULL, [YAR_OPT_PACKAGER => "json"]);
//custom timeout
Yar_Concurrent_Client::call($webserviceApi, "mul", [4,4], "callback", NULL, [YAR_OPT_TIMEOUT => 1]);
//发送所有的已经通过 Yar_Concurrent_Client::call()注册的并行调用, 并且等待返回. the error_callback is optional
Yar_Concurrent_Client::loop("callback", "error_callback");
} catch (Yar_Server_Exception $ex) {
var_dump($ex->getMessage());
}catch(Yar_Client_Exception $ex){
var_dump($ex->getMessage());
}
持久调用
在Yar 2.1.0之后,如果YAR_OPT_PERSISTENT设置为true,那么Yar就可以使用HTTP keep-alive来加速对同一个地址的重复调用,链接将在PHP请求生命周期结束时释放。
$client = new Yar_Client("http://host/api/");
$client->SetOpt(YAR_OPT_PERSISTENT, 1);
$result = $client->some_method("parameter");
/* The following calls will speed up due to keep-alive */
$result = $client->some_other_method1("parameter");
$result = $client->some_other_method2("parameter");
$result = $client->some_other_method3("parameter");
自定义主机名解析
在Yar 2.1.0之后,如果Yar运行在HTTP协议上,则可以使用YAR_OPT_RESOLVE来定义自定义主机名解析。
$client = new Yar_Client("http://host/api/");
$client->SetOpt(YAR_OPT_RESOLVE, "host:80:127.0.0.1");
/* call goes to 127.0.0.1 */
$result = $client->some_method("parameter");
http代理
在Yar 2.2.1之后,如果Yar运行在HTTP协议上,则可以使用YAR_OPT_PROXY来定义HTTP代理,例如fidder或charles。
$client = new Yar_Client("http://host/api/");
$client->SetOpt(YAR_OPT_PROXY,"127.0.0.1:8888"); //http proxy , Since 2.2.0
/* call goes to 127.0.0.1 */
$result = $client->some_method("parameter");