php扩展之Yar
Yar 是一个轻量级, 高效的RPC框架, 它提供了一种简单方法来让PHP项目之间可以互相远程调用对方的本地方法. 并且Yar也提供了并行调用的能力. 可以支持同时调用多个远程服务的方法.
情况: 有个业务场景,需要本地项目去调用一个服务层的相关方法实现相应的功能,一般情况,我可以通过普通的http的方式进行请求即可,但是如果只是这个服务是内部使用,那么可以使用rpc的方式进行替代.好处自不必多说,基于tcp传输,支持并发
实例参考:http://hk2.php.net/manual/zh/yar.examples.php
结合在项目中使用:
首先介绍服务端:RpcServer.php
<?php namespace app\index\logic; /** * rpc基类(服务端) */ class RpcServer { private static $signs = [ 'sign1', //不同的来源Salt不同 'sign2', ]; // 验证签名 protected function checkSign($params,$sign) { if(empty($sign)){ return false; } ksort($params); $signStr = ''; foreach($params as $key => $val) { if(empty($val) || $val == $sign) continue; $signStr .= $key.'='.$val.'&'; } $signStr = rtrim($signStr,'&'); foreach (self::$signs as $v){ if(md5($signStr.$v) === $sign){ return true; } } } // 处理结果 protected function response($status,$data) { $response = [ 'status' => $status, 'message' => '', //状态码对应的信息(从配置文件中获取) 'data' => $data, ]; return $response; } }
服务端方法:
<?php namespace app\index\logic; class User extends RpcServer { // 用户扩展信息 public function userExt($ids) { // 1.验证签名 // 2.逻辑处理 // 3.结果返回 return $ids; } // 用户基础信息 public function userBase($ids) { return $ids; } }
客户端:RpcClient.php
<?php namespace app\index\logic; /** * rpc基类(客户端) */ class RpcClient { private static $signs = [ 'sign1', //不同来源 'sign2' ]; private $callBack; private $callNum = 0; /** * 取得签名 * @param $params 接口调用时的参数 */ protected function getSign($params,$type) { ksort($params); $signStr = ''; foreach($params as $key => $val) { if(empty($val)) continue; $signStr .= $key.'='.$val.'&'; } $signStr = rtrim($signStr,'&'); return md5($signStr.self::$signs[$type]); } /** * 调用服务端接口 * @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,'callback1'],[$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 callback1($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' ); } }
客户端调用:
<?php namespace app\index\logic; // 相关测试 class Test extends RpcClient { public function testRpc() { $api = 'http://thinkphp.com/index/rpc/users'; // $this->call($api,'userExt',[1,2],false,'callback'); $this->call($api,'userBase',[3,4],false,'callback'); $this->call($api,'userBase',[5],false,'callback'); $this->loop(); return false; // $client = new yar_client("http://thinkphp.com/index/rpc/user"); // $ret = $client->userInfo([1,2]); // var_dump($ret); } // 回调数据 public function callback($data,$callinfo) { var_dump(func_get_args());die; // static $a = []; // $a[] = json_encode(func_get_args()); // print_r($a); // error_log(json_encode(func_get_args() ),3,'rpc.log' ); } }
即可实现简单的rpc调用
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库