目录

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(Yet Another RPC framework)是一个轻量级支持并行调用的PHP RPC框架,是我还在微博的时候为了优化微博的性能而开发的一个工具,Yar的并行调用在微博被大量应用以降低用户请求耗时。 最近还是因为疫情,我把Yaf,Yaconf都优化了一轮,今天也完成了Yar的优化(事实上,Yar之前写的就还不错,没啥可优化的,哈哈),也新增了俩个能力。我来简单介绍下:

自定义主机名解析

在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"); 

github官方地址及鸟哥关于yar的文章

Light, concurrent RPC framework for PHP & C. Contribute to laruence/yar development by creating an account on GitHub.

Yar(Yet Another RPC framework)是一个轻量级支持并行调用的PHP RPC框架,是我还在微博的时候为了优化微博的性能而开发的一个工具,Yar的并行调用在微博被大量应用以降低用户请求耗时。 最近还是因为疫情,我把Yaf,Yaconf都优化了一轮,今天也完成了Yar的优化(事实上,Yar之前写的就还不错,没啥可优化的,哈哈),也新增了俩个能力。我来简单介绍下:

Yar(yet another RPC framework, 教主问我为啥都是Ya打头, 呵呵, 因为这样名字好起)是我在3个多月前, 为了解决一个实际的问题, 而开发的一个PHP扩展的, RPC框架, 和现有的RPC框架(xml-rpc, soap)不同, 这是一个轻量级的框架, 支持多种打包协议(msgpack, json, php), 并且最重要的一个特点是, 它是可并行化的..