继上一篇什么是RPC,这一篇主要是记录原生PHP实现RPC的过程。
RPC要完成的事情
(1)调用方感觉就像调用本地函数一样
(2)RPC框架又分为client部分与server部分,负责把整个非的各类复杂性屏蔽,这些复杂性就是RPC框架的职责。
(架构师之路抄一张图)
PHP代码
上图可以看到有socket,其实原理大致已经知道了。
server端
需要用到的函数就是这些
stream_socket_server
stream_socket_accept
Fread
Fwrite
fclose
client端
需要的函数
stream_socket_client
fwrite
Fread
fclose
server.php代码
<?php
//创建一个套接字
$stock = stream_socket_server("tcp://0.0.0.0:1994", $errno, $errstr);
if (!$stock) {
echo '异常代码:' . $errno . ',异常信息' . $errstr;
exit;
}
while (true) { //死循环保证不被断开
try {
$return_data = [];
//开始连接
$buff = @stream_socket_accept($stock);
//读取文件
$data = @fread($buff, 2048);
//客户端以json格式发送数据,也可以使用序列化
$json_data = json_decode($data, true);
$class = $json_data['class']; //客户端访问的类
$new_file = $class . '.php';
if (!file_exists($new_file)) {
throw new Exception('文件不存在', '-1');
}
require_once $new_file; //引入类
$method = $json_data['method']; //客户端访问方法
$user_obj = new $class();
if (isset($json_data['param']) && !empty($json_data['param'])) {
$param = $json_data['param'];
$server_data = $user_obj->$method($param);
}else{
$server_data = $user_obj->$method();
}
$return_data=[
'code'=>200,
'data'=>$server_data,
'msg'=>'success'
];
$return_data = json_encode($return_data);
//输出字节流
@fwrite($buff, $return_data);
@fclose($buff);
} catch (Exception $e) {
$err=[
'code'=>$e->getCode(),
'data'=>[],
'msg'=>$e->getMessage(),
];
$err = json_encode($err);
@fwrite($buff, $err);
@fclose($buff);
}
}
server.php 需要在命令行模式启动,启动以后不要关闭。因为开启以后为常驻内存,如果修改server.php需要重新启动。
新建一个User类等待使用
<?php
class user{
//使用魔术方程,可以在随意输入方法名和参数
public function __call($name, $arguments)
{
// TODO: Implement __call() method.
return "Calling object method '$name'的参数有多个,分别是:".implode ('、',$arguments)."<br/>" ;
}
}
client.php代码
<?php
//使用ip和port要和server配置一样
$client = stream_socket_client("tcp://127.0.0.1:1994", $errno,$errstr);
if(!$client){
echo '异常代码:'.$errno.',异常信息:'.$errstr;exit;
}
//客户端命令行模式
if (PHP_SAPI=='cli'){
$class=$argv[1];
$method=$argv[2];
$param=$argv[3];
}else{
//客户端web访问模式
$class=$_GET['class'];
$method=$_GET['method'];
$param=$_GET['param'];;
}
$data=[
'class'=>$class,
'method'=>$method,
'param'=>$param,
];
$_data = json_encode($data);
fwrite($client, $_data);
$server_data = fread($client, 2048);
$resutl = json_decode($server_data,true);
fclose($client);
print_r($resutl);
启动client.php
命令行模式
php client.php User myname brown
web访问
http://127.0.0.1/RPC/php/client.php?class=User&method=qwe¶m=2
前面换成实际ip即可
这样的一个简单RPC框架就完成了。部署到linux也是一个道理。原生PHP个人觉得效率太低,远不如workman和swoole。
linux部署常驻后台可以使用supervisor。
下一篇文章会研究rpc框架和tp框架结合,还有workman和swoole和tp框架的结合。