文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> 软件教程>PHP实现RPC(简版)的讲解

PHP实现RPC(简版)的讲解

时间:2020-12-30  来源:互联网

php独特的语法混合了C、java、Perl以及PHP自创新的语法。它可以比CGI或者Perl更快速的执行动态网页。

part-00321-548.jpg

概述

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

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

自己实现

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

思路

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

通信问题

定义传输的数据格式

如何封装后可以达到像调用本地函数一样的效果

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

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

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

开始实现

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

经过一番摸索, 看下结果

服务器内容:

class RpcServer{

    private $port = 0; // 监听端口号

    private $host = ''; // IP

    public 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();

调用方:

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);

结果:

5e898c5991dbf.png

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

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

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

继续

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

WHAT

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

WHY

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

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

HOW

那么如何实现RPC呢?

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

网络通信

信息格式

对象状态保存

1.网络通信

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

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

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

2.信息格式

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

3.对象状态保存

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

过程

个人理解的RPC调用过程:

客户端创建RPC对象

客户端调用方法

RPC解析方法并将对象及参数做序列化

RPC通过网络连接发送方法调用

服务端接收到方法调用, 解析对象及参数反序列化

服务端执行方法并将结果序列化返回

客户端接收到结果并进行解析, 返回给本地调用者

拿到最终结果

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

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

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

个人理解, 以上...

  PHP,一个嵌套的缩写名称,是英文超级文本预处理语言(PHP:HypertextPreprocessor)的缩写。PHP是一种HTML内嵌式的语言,PHP与微软的ASP颇有几分相似,都是一种在服务器端执行的嵌入HTML文档的脚本语言,语言的风格有类似于C语言,现在被很多的网站编程人员广泛的运用。

相关阅读更多 +
最近更新
排行榜 更多 +
元梦之星最新版手游

元梦之星最新版手游

棋牌卡牌 下载
我自为道安卓版

我自为道安卓版

角色扮演 下载
一剑斩仙

一剑斩仙

角色扮演 下载