PHP创建简单RPC服务案例详解
发布:smiling 来源: PHP粉丝网 添加日期:2022-05-13 14:10:24 浏览: 评论:0
这篇文章主要介绍了PHP创建简单RPC服务案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下。
RPC 定义
RPC(Remote Procedure Call)即远程过程调用,指被调用方法的具体实现不在程序运行本地,而是在别的某个地方。主要应用于不同的系统之间的远程通信和相互调用。
如 A 调用 B 提供的 remoteAdd 方法:
首先A与B之间建立一个TCP连接;
然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送出去;
B接受A发送过来的字节流,然后反序列化得到目标方法名,方法参数,接着执行相应的方法调用(可能是localAdd)并把结果30返回;
A接受远程调用结果
有些远程调用选择比较底层的 socket 协议,有些远程调用选择比较上层的 HTTP 协议。
远程调用的好处:
解耦:当方法提供者需要对方法内实现修改时,调用者完全感知不到,不用做任何变更;这种方式在跨部门,跨公司合作的时候经常用到,并且方法的提供者我们通常称为:服务的暴露方
这里使用 PHP Socket 来创建一个服务端和客户端,目录结构如下:
服务端
- <?php
- class RpcServer {
- protected $server = null;
- public function __construct($host, $port, $path)
- {
- // 创建一个 Socket 服务
- if(($this->server = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
- exit("socket_create() 失败的原因是:".socket_strerror($this->server)."\n");
- }
- if(($ret = socket_bind($this->server,$host,$port)) < 0) {
- exit("socket_bind() 失败的原因是:".socket_strerror($ret)."\n");
- }
- if(($ret = socket_listen($this->server,3)) < 0) {
- exit("socket_listen() 失败的原因是:".socket_strerror($ret)."\n");
- }
- // 判断 RPC 服务目录是否存在
- $realPath = realpath(__DIR__ . $path);
- if ($realPath === false || !file_exists($realPath)) {
- exit("{$path} error \n");
- }
- do {
- $client = socket_accept($this->server);
- if($client) {
- // 一次性读取
- $buf = socket_read($client, 8024);
- echo $buf;
- //解析客户端发送过来的协议
- $classRet = preg_match('/Rpc-Class:\s(.*);\r\n/i', $buf, $class);
- $methodRet = preg_match('/Rpc-Method:\s(.*);\r\n/i', $buf, $method);
- $paramsRet = preg_match('/Rpc-Params:\s(.*);\r\n/i', $buf, $params);
- if($classRet && $methodRet) {
- $class = ucfirst($class[1]);
- $method = $method[1];
- $params = json_decode($params[1], true);
- $file = $realPath . '/' . $class . '.php'; // 类文件需要和类名一致
- $data = ''; // 执行结果
- // 判断类文件是否存在
- if(file_exists($file)) {
- // 引入类文件
- require_once $file;
- // 实例化类
- $rfc_obj = new ReflectionClass($class);
- // 判断该类指定方法是否存在
- if($rfc_obj->hasMethod($method)) {
- // 执行类方法
- $rfc_method = $rfc_obj->getMethod($method);
- $data = $rfc_method->invokeArgs($rfc_obj->newInstance(), [$params]);
- } else {
- socket_write($client, 'method error');
- }
- //把运行后的结果返回给客户端
- socket_write($client, $data);
- }
- } else {
- socket_write($client, 'class or method error');
- }
- // 关闭客户端
- socket_close($client);
- }
- }while(true);
- }
- public function __destruct()
- {
- socket_close($this->server);
- }
- }
- new RpcServer('127.0.0.1',8080,'./service');
客户端
- <?php
- class RpcClient {
- protected $client = null;
- protected $url_info = []; // 远程调用 URL 组成部分
- public function __construct($url)
- {
- // 解析 URL
- $this->url_info = parse_url($url);
- }
- public function __call($name, $arguments)
- {
- // 创建一个客户端
- $this->client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
- if(!$this->client) {
- exit('socket_create() 失败');
- }
- socket_connect($this->client, $this->url_info['host'], $this->url_info['port']);
- // 传递调用的类名
- $class = basename($this->url_info['path']);
- // 传递调用的参数
- $args = '';
- if(isset($arguments[0])) {
- $args = json_encode($arguments[0]);
- }
- // 向服务端发送我们自定义的协议数据
- $proto = "Rpc-Class: {$class};".PHP_EOL
- ."Rpc-Method: {$name};".PHP_EOL
- ."Rpc-Params: {$args};".PHP_EOL;
- socket_write($this->client, $proto);
- // 读取服务端传来的数据
- $buf = socket_read($this->client, 8024);
- socket_close($this->client);
- return $buf;
- }
- }
- $rpcClient = new RpcClient('http://127.0.0.1:8080/news');
- echo $rpcClient->display(['title'=>'txl']);
- echo $rpcClient->display(['title'=>'hello world']);
服务类 News
- <?php
- class News {
- public function display($data)
- {
- return json_encode(['result'=>"News display(), title is {$data['title']}"]);
- }
- }
运行测试:
Client
Server
Tags: PHP创建简单RPC服务
- 上一篇:php之redis短线重连案例讲解
- 下一篇:最后一页
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)