概述

RPC这个东西是什么? 第一次听说他, 还要在它的前边加个G, 当时我以为GRPC是一项技术, 后来才知道, 并不是这样. GRPC只是RPC的谷歌实现.

谷歌搜了一下, RPC就是一种: 远程函数调用, 看到这里, 我已经等不及了, 不往下看了, 先自己实现一个. 如果只给你这样一个概念, 如何实现调用远程函数的功能呢?

自己实现

自己尝试实现一个粗糙的PHP版本. (不想看可以跳过的)

思路

远程调用, 只需要解决下面问题:

  1. 通信问题
  2. 定义传输的数据格式
  3. 如何封装后可以达到像调用本地函数一样的效果

先来解决通信问题, 直接粗暴的tcp socket

传输的数据格式, 直接用json进行传输

调用本地函数?? 这就要借助一下PHP的魔术函数了, __call() 这个函数是一个类调用不存在的方法时会跑到这里来, 所以, 我们返回一个类, 在call方法中进行远程调用, 这样, 在本地看来就只是在调用一个方法.

开始实现

PHP中进行socket连接十分简单, 直接调用系统函数. 通信问题解决了, 剩下的就是传输数据了, so easy

经过一番摸索, 看下结果

服务器内容:

<?php
class RpcServer{private $port = 0; // 监听端口号private $host = ''; // IPpublic function __construct($host, $port){$this->host = $host;$this->port = $port;}/*** 运行, 监听端口并处理*/public function run(){// 创建socket$server = stream_socket_server("tcp://{$this->host}:{$this->port}");if(empty($server)) throw new Exception('创建套接字失败');// 监听while (true){$client = stream_socket_accept($server);if(empty($client)) continue;// 处理请求$this->disposeClient($client);fclose($client);}}private function disposeClient($client){$buf = fread($client, 4096);$array = json_decode($buf, true);// 创建对象并调用方法$class = $array['class'] ?? '';$method = $array['method'] ?? '';$params = $array['params'] ?? [];$instance = new $class();$result = $instance->$method(...$params);fwrite($client, json_encode($result));}
}
// 测试调用类
class Test{public function tt(){return 'return_tt';}public function add($a, $b){return $a + $b;}
}(new RpcServer('127.0.0.1', 8888))->run();

调用方:

<?php
class RpcClient{private $urlInfo = null;private $className = '';private function __construct($url, $className){$this->urlInfo = parse_url($url);$this->className = $className;}public static function getInstance($className){return new RpcClient('127.0.0.1:8888', $className);}public function __call($name, $arguments){// 创建客户端$client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}");if(empty($client)) return null;// 发送数据fwrite($client, json_encode(['class' => $this->className,'method' => $name,'params' => $arguments,]));// 接收返回$data = fread($client, 4096);// 关闭客户端fclose($client);return json_decode($data, true);}
}$test = RpcClient::getInstance('Test');
echo $test->tt(), PHP_EOL;
echo $test->add(4, 6);

结果:

嗯, 还阔以. 当然, 问题还是有很多的, 比如不能实现保存对象的修改状态等等.

其实对象可以通过序列化和反序列化来传输, 额, Java中, 不知道PHP有没有这种技术.

当然, 一个RPC中必然大量使用反射序列化动态加载代理网络请求等等, 这只是一个超级超级粗糙的示例.

继续

nice, 自己做完了, 对RPC是个什么东西有了一个基本的概念.

WHAT

RPC是什么? 简单说, 就是远程函数调用. 字面意思, 很好理解.

WHY

看到一个技术, 一定会问的一个问题就是: 为什么? 一个技术基本不会平白无故出现, 都是为了解决某些问题, 那么RPC解决了什么问题呢? 字面含义: 远程函数调用

为什么要进行远程函数调用, 把函数拿过来本地调用不就好了? 还不用走网络IO, 速度更快一些. 很好, 现在假设, 你真的这样做了, 当项目变得庞大, 你想要进行拆分, 拆分后的有: 项目A, 项目B…, 这时, 你发现这些拆分的项目部分逻辑是重叠的, 比如用户信息相关, 怎么办? 如果不抽出来, 以后的维护成本会变得很高, 一处改处处改. 如果抽出来, 跨项目如何进行调用? 哎, 走过路过不要错过, RPC推荐给你.

HOW

那么如何实现RPC呢?

在刚才使用PHP简单实现中, 已经发现了. 需要解决的问题如下:

  1. 网络通信
  2. 信息格式
  3. 对象状态保存

1.网络通信

说到底, 网络通信不过两种: tcp udp.

有没有使用udp实现的RPC呢? 貌似也有.

使用tcp协议实现的RPC也有, 当然, 不光传输层协议, 也有直接通过应用层协议: httpwebsocket等等建立连接的. 当然, 如果需要频繁调用, 可以不断开tcp连接, 在一段时间内一直保持连接, 避免频繁握手.

2.信息格式

信息格式就有很多选择了, jsonxml等等, 也可以自己定制, 只要发送端和接收端统一信息格式就行了.

3.对象状态保存

对于一个类的调用, 通常都会有类状态修改的操作, 比如调用setName方法, 如何保存对象的信息呢? 当然, 可以服务端将对象在内存中的信息直接序列化发回去, 当客户端下次调用时携带序列化信息, 服务端接收后反序列化还原对象继续操作.

过程

个人理解的RPC调用过程:

  1. 客户端创建RPC对象
  2. 客户端调用方法
  3. RPC解析方法并将对象及参数做序列化
  4. RPC通过网络连接发送方法调用
  5. 服务端接收到方法调用, 解析对象及参数反序列化
  6. 服务端执行方法并将结果序列化返回
  7. 客户端接收到结果并进行解析, 返回给本地调用者
  8. 拿到最终结果

RPC适用于内部网络不同项目之间的通信, 如果是对外暴露的, 个人感觉还是通过接口的形式吧.

使用RPC显然会丧失一部分性能, 毕竟调用要走网络IO, 尽管是内网, 仍然要比本地调用慢上一些, 但带来了更好的可扩展性和可维护性, 感觉还是不错的.

之后如果用到的话, 拉个框架看看源码.

个人理解, 以上…

PHP实现RPC(简版)相关推荐

  1. 怎么改PHP_PHP实现RPC(简版)

    概述 RPC这个东西是什么? 第一次听说他, 还要在它的前边加个G, 当时我以为GRPC是一项技术, 后来才知道, 并不是这样. GRPC只是RPC的谷歌实现. 谷歌搜了一下, RPC就是一种: 远程 ...

  2. [置顶]完美简版学生信息管理系统(附有源码)管理系统

    简版学生信息管理系统 目前为止找到的简版系统中最新.最全的java类管理系统 点击进入简版系统 如果无法直接连接,请进入: https://blog.csdn.net/weixin_43419816/ ...

  3. 7句话让Codex给我做了个小游戏,还是极简版塞尔达,一玩简直停不下来

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 梦晨 萧箫 发自 凹非寺 量子位 | 公众号 QbitAI 什么,7 ...

  4. 来,一起手撸一个简版 Redis(附源码)

    点击上方 视学算法,选择 设为星标 优质文章,及时送达 作者 | 凯京技术团队 来自 | my.oschina.net/keking/blog/3037372 今天主要介绍两个开源项目,然后创建应用最 ...

  5. 2012年中国移动地图和导航市场研究报告简版

    2019独角兽企业重金招聘Python工程师标准>>> 2012年中国移动地图和导航市场研究报告简版 2012年中国移动地图和导航市场用户规模为2.53亿人,增长率为62.2%.伴随 ...

  6. 10分钟手撸极简版ORM框架!

    最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernte这种ORM框架,它们是如何实现的呢? 为了能够让小伙伴们 ...

  7. 《数字孪生体技术白皮书(2019)》(简版)全文

    来源:<数字孪生体实验室原创> 12月27日,数字孪生体实验室与安世亚太联合正式发布了<数字孪生体技术白皮书(2019)>. 白皮书的第一部分关注对数字孪生体的抽象和总结.无论 ...

  8. Dockerfile 简版大全,附赠编写实例

    基础镜像可以用于创建Docker容器.镜像可以非常基础,仅仅包含操作系统:也可以非常丰富,包含灵巧的应用栈,随时可以发布.当你在使用Docker构建镜像的时候,每一个命令都会在前一个命令的基础上形成一 ...

  9. react-redux简版实现

    Provider组件 Provider用于建立能够被子组件访问的全局属性,核心API有两个: childContextTypes静态属性,用于指定被子组件访问的全局属性类型 getChildConte ...

最新文章

  1. 【ESP8266】使用ESP8266 NONOS SDK的JSON API
  2. xml web service
  3. 日期型转json格式(springboot)
  4. 万物皆可文本时代来临?如何搞定NLP最强模型GPT
  5. python 端口扫描
  6. ecshop分页类assign_pager分析和扩展
  7. 【CodeForces - 1082B】Vova and Trophies (贪心模拟,暴力)
  8. mysql-优化班学习-8-20170606-MySQL索引
  9. 将数组项复制到另一个数组中
  10. Win10 OPNET14.5+VS2010 安装教程
  11. 平面方程、夹角与点到平面的距离
  12. poi合并docx文档
  13. 有没有无痛无害的人体成像方法?OCT(光学相干断层扫描)了解一下
  14. Azido-TAT,大环化合物,双功能螯合剂的性质
  15. 计算机技术与应用论文,计算机应用技术论文
  16. 显示器购买攻略【小白必看】
  17. 泛型学习笔记:泛型使用的注意点、泛型在继承方面的体现、自定义泛型结构、泛型应用举例、通配符
  18. office2010打开excel文档时为空白的解决方法
  19. Nexus Maven私服配置
  20. 一个微服务业务系统的中台构建之路

热门文章

  1. Linux的实际操作:文件目录类的实用指令(cat more less)
  2. JAVA入门级教学之(对象的使用)
  3. mysql api 连接池_SpringBoot-整合HikariCP连接池
  4. 梦幻西游服务器每周几维护,梦幻西游5月6日维护公告:唯美版地图不再更新
  5. spring 2.0核心技术与最佳实践 pdf_推荐 Spring Boot 实践学习案例大全 数据缓存 和中间件 安全权限...
  6. 计算机网络中的数据链路层
  7. leetcode 142 --- linked-list-cycle-ii
  8. word刷子刷格式_Excel技巧—开始菜单之格式刷六大功能
  9. mysql 5.1.53_mysql 5.1.53免安装版的优化配备和精简
  10. linux spi驱动分析 三,Linux下SPI驱动分析