先说windows客户端的安装
yar扩展下载地址:https://pecl.php.net/package/yar
下载对应的版本
点击DLL可以查看支持的PHP版本,我本地是phpstudy搭建的环境,php版本是7.19.nts
所以我下载了7.1 Non Thread Safe (NTS) x64
解压后里面的php_yar.dll和php_yar.pdb文件放到对应的php版本ext下面
我的是D:\phpstudy_pro\Extensions\php\php7.1.9nts\ext
然后修改php.ini文件增加 extension=php_yar.dll
php.ini文件可以从phpstudy设置中打开对应版本配置文件
重启phpstudy就安装完成了
linux的安装:
安装yar要先装msgpack
安装msgpack
首先进入~目录
find / -name phpize //查看phpize文件位置 我的是 /www/server/php/71/bin/phpize
使用 wegt或者curl下载msgpack
wegt http://pecl.php.net/get/msgpack-2.0.2.tgz 或者 curl -O http://pecl.php.net/get/msgpack-2.0.2.tgz
tar -xzvf msgpack-2.0.2.tgz //解压文件
cd msgpack-2.0.2 //进入目录
/www/server/php/71/bin/phpize //输入自己的phpize路径
./configure --with-php-config=/www/server/php/71/bin/php-config //设置编译配置 我的是/www/server/php/71/bin/php-config
make && make install //开始编译
安装完成后会有个文件位置提示,我的是/www/server/php/71/lib/php/extensions/no-debug-non-zts-20200315
查看自己目录下面是否有msgback.so
修改php.ini文件最后添加extension=/www/server/php/71/lib/php/extensions/no-debug-non-zts-20200315/msgback.so安装yar
首先进入~目录
cd
find / -name phpize //查看phpize文件位置 我的是 /www/server/php/71/bin/phpize
使用 wegt或者curl下载yar 我的服务器php版本也是7.1的所以下载也是2.0.5的
wegt http://pecl.php.net/get/yar-2.0.5.tgz 或者 curl - O http://pecl.php.net/get/yar-2.0.5.tgz
tar -xzvf yar-2.0.5.tgz //解压文件
cd yar-2.0.5 //进入目录
/www/server/php/71/bin/phpize //输入自己的phpize路径
./configure --with-php-config=/www/server/php/71/bin/php-config //设置编译配置 我的是/www/server/php/71/bin/php-config
make && make install //开始编译
安装完成后会有个文件位置提示,我的是/www/server/php/71/lib/php/extensions/no-debug-non-zts-20200315
查看自己目录下面是否有yar.so
修改php.ini文件最后添加extension=/www/server/php/71/lib/php/extensions/no-debug-non-zts-20200315/yar.so
重启PHP就安装完成了
使用:
服务端是linux的,本地是客户端是windows
服务端安装了tp5.0,直接在index目录测试
新建RpcServer.php文件,用来做控制
<?phpnamespace app\index\controller;/*** rpc基类(服务端)*/
class RpcServer
{//秘钥protected $key ='约定好的秘钥';//生成签名public function getSign($arr){if(empty($arr)){return false;}//去除数组中的空值$arr = array_filter($arr);//如果数组中有签名删除签名if(isset($arr['sing'])){unset($arr['sing']);}//按照键名字典排序ksort($arr);//生成URL格式的字符串$str = http_build_query($arr)."&key=".$this->key;$str = $this->arrToUrl($str);return strtoupper(md5($str));}//获取签名 待签名的数组public function setSing($arr){$arr['sing'] = $this->getSign($arr);return $arr;}//URL解码为中文public function arrToUrl($str){return urldecode($str);}//验证签名public function checkSing($arr, $form_sing){//获取签名$sing = $this->getSign($arr);if($sing == $form_sing){return true;} else {return false;}}
}
然后要开放访问的Test.php文件
<?phpnamespace app\index\controller;class Testextends RpcServer
{//因为tp自动访问index要不会有报错public function index() {//return 12312;}/*** Add two operands* @param interge * @return interge*/public function add($a, $b, $c) {//验证签名if ($this->checkSing([$a,$b], $c)) {return $this->_add($a, $b);} else {return '签名错误';}}/*** Protected methods will not be exposed* @param interge * @return interge*/protected function _add($a, $b) {return $a + $b;}
}$server = new \Yar_Server(new Test());
$server->handle();
服务端就算弄好了,访问对应控制器后显示的是
然后是客户端,同样是tp5.0
新建RpcClient.php文件
<?phpnamespace app\index\controller;/*** rpc基类(客户端)*/
class RpcClient
{//秘钥private $sign_key ='约定的秘钥';private $callBack;private $callNum = 0;/*** 调用服务端接口* @param $server Api server* @param $api 接口* @param $params 参数* @param $openSign 开启签名* @param $callBack 回调*/ public function call($server,$api,$params,$openSign=false,$callBack=null){if($openSign){$params['sign'] = $this->getSign($params);}if($callBack === null){$client = new \Yar_Client($server);return call_user_func_array([$client,$api], $params);}$this->callNum ++;$this->callBack = $callBack;return \Yar_Concurrent_Client::call($server,$api,$params,array($this, 'ApiClientCallBack'));}/*** 执行并发调用*/public function loop(){return \Yar_Concurrent_Client::loop([$this,'callback_first'],[$this,'error_callback']); }/*** 并发调用回调* @param $retval* @param $callinfo*/public function ApiClientCallBack($retval,$callinfo){ if($callinfo === null){return $this->callBack($retval,$callinfo);}static $data = array();$data[] = $retval; //并发if(count($data) == $this->callNum){$fn = $this->callBack;return $this->$fn($data,$callinfo);}}// public function callback_first($retval, $callinfo){if ($callinfo == NULL) {echo "现在, 所有的请求都发出去了, 还没有任何请求返回\n";} else {echo "这是一个远程调用的返回, 调用的服务名是", $callinfo["method"], ". 调用的sequence是 " , $callinfo["sequence"] , "\n";var_dump($retval);}}// 异常回调public function error_callback($type, $error, $callinfo){error_log(json_encode(func_get_args() ),3,'rpc.log' );}//生成签名public function getSign($arr){//去除数组中的空值$arr = array_filter($arr);//如果数组中有签名删除签名if(isset($arr['sing'])){unset($arr['sing']);}//按照键名字典排序ksort($arr);//生成URL格式的字符串$str = http_build_query($arr)."&key=".$this->sign_key;$str = $this->arrToUrl($str);return strtoupper(md5($str));}
}
实际发送访问发送请求的文件Test.php
<?phpnamespace app\index\controller;use app\common\controller\Frontend;/*** 会员中心*/
class Test extends RpcClient
{ public function testRpc(){//同步$client = new \yar_client("服务端地址/index/test");$ret = $client->add(1,2);//可以调用服务端控制器下的方法var_dump($ret);exit();//异步并发$api = '服务端地址/index/test';$this->call($api,'add',[1,2],true,'callback');$this->call($api,'add',[3,4],true,'callback');$this->call($api,'add',[5,6],true,'callback');$this->loop();return false;}// 回调数据public function callback($data,$callinfo){echo "<pre>";echo "data:";//异步返回的参数var_dump($data);echo "callinfo:";//调用的方法var_dump($callinfo);}
}
这样访问testRpc方法就可以调用服务端控制器下的方法了