php rpc怎么实现?-php教程

资源魔 37 0

1.甚么是rpc

RPC全称为Remote Procedure Call,翻译过去为“近程进程挪用”。今朝,支流的平台中都支持各类近程挪用技巧,以餍足散布式零碎架构中没有同的零碎之间的近程通讯以及互相挪用。近程挪用的使用场景极端宽泛,完成的形式也各式百般。

2.从通讯协定的层面

基于HTTP协定的(例如基于文本的SOAP(XML)、Rest(JSON),基于二进制Hessian(Binary))
基于TCP协定的(通常会借助Mina、Netty等高功能网络框架)

3.从没有同的开发言语战争台层面

单种言语或平台特定支持的通讯技巧(例如Java平台的RMI、.NET平台Remoting)
支持跨平台通讯的技巧(例如HTTP Rest、Thrift等)

4.从挪用进程来看

同步通讯挪用(同步RPC)
异步通讯挪用(MQ、异步RPC)

5.常见的几种通讯形式

近程数据同享(例如:同享近程文件,同享数据库等完成没有同零碎通讯)
音讯行列步队
RPC(近程进程挪用)

6.php完成简略的rpc

目次构造

40d784037eb297e737a45555afce217.png

rpc效劳端

<?php/**
 * User: yuzhao
 * CreateTime: 2018/11/15 下战书11:46
 * Description: Rpc效劳端
 */class RpcServer {    /**
     * User: yuzhao
     * CreateTime: 2018/11/15 下战书11:51
     * @var array
     * Description: 此类的根本设置装备摆设
     */
    private $params = [        'host'  => '',  // ip地点,列进去的目的是为了敌对看进去此变量中存储的信息
        'port'  => '', // 端口
        'path'  => '' // 效劳目次
    ];    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:14
     * @var array
     * Description: 本类罕用设置装备摆设
     */
    private $config = [        'real_path' => '',        'max_size'  => 2048 // 最年夜接纳数据巨细
    ];    /**
     * User: yuzhao
     * CreateTime: 2018/11/15 下战书11:50
     * @var nul
     * Description:
     */
    private $server = null;    /**
     * Rpc constructor.
     */
    public function __construct($params)
    {        $this->check();        $this->init($params);
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:0
     * Description: 须要验证
     */
    private function check() {        $this->serverPath();
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/15 下战书11:48
     * Description: 初始化须要参数
     */
    private function init($params) {        // 将通报过去的参数初始化
        $this->params = $params;        // 创立tcpsocket效劳
        $this->createServer();
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:0
     * Description: 创立tcpsocket效劳

     */
    private function createServer() {        $this->server = stream_socket_server("tcp://{$this->params['host']}:{$this->params['port']}", $errno,$errstr);        if (!$this->server) exit([
            $errno,$errstr
        ]);
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/15 下战书11:57
     * Description: rpc效劳目次
     */
    public function serverPath() {
        $path = $this->params['path'];
        $realPath = realpath(__DIR__ . $path);        if ($realPath === false ||!file_exists($realPath)) {            exit("{$path} error!");
        }        $this->config['real_path'] = $realPath;
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/15 下战书11:51
     * Description: 前往以后工具
     */
    public static function instance($params) {        return new RpcServer($params);
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:06
     * Description: 运转
     */
    public function run() {        while (true) {
            $client = stream_socket_accept($this->server);            if ($client) {                echo "有新衔接\n";
                $buf = fread($client, $this->config['max_size']);
                print_r('接纳到的原始数据:'.$buf."\n");                // 自界说协定目的是拿到类办法以及参数(可改为本人界说的)
                $this->parseProtocol($buf,$class, $method,$params);                // 执行办法
                $this->execMethod($client, $class, $method, $params);                //封闭客户端
                fclose($client);                echo "封闭了衔接\n";
            }
        }
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:19
     * @param $class
     * @param $method
     * @param $params
     * Description: 执行办法
     */
    private function execMethod($client, $class, $method, $params) {        if($class && $method) {            // 首字母转为年夜写
            $class = ucfirst($class);
            $file = $this->params['path'] . '/' . $class . '.php';            //判别文件能否存正在,假如有,则引入文件
            if(file_exists($file)) {                require_once $file;                //实例化类,并挪用客户端指定的办法
                $obj = new $class();                //假如有参数,则传入指定参数
                if(!$params) {
                    $data = $obj->$method();
                } else {
                    $data = $obj->$method($params);
                }                // 打包数据
                $this->packProtocol($data);                //把运转后的后果前往给客户端
                fwrite($client, $data);
            }
        } else {
            fwrite($client, 'class or method error');
        }
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:10
     * Description: 解析协定
     */
    private function parseProtocol($buf, &$class, &$method, &$params) {
        $buf = json_decode($buf, true);
        $class = $buf['class'];
        $method = $buf['method'];
        $params = $buf['params'];
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:30
     * @param $data
     * Description: 打包协定
     */
    private function packProtocol(&$data) {
        $data = json_encode($data, JSON_UNESCAPED_UNICODE);
    }

}

RpcServer::instance([    'host'  => '127.0.0.1',    'port'  => 8888,    'path'  => './api'])->run();

rpc 客户端

<?php/**
 * User: yuzhao
 * CreateTime: 2018/11/16 上午12:2
 * Description: Rpc客户端
 */class RpcClient {    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:21
     * @var array
     * Description: 挪用的地点
     */
    private $urlInfo = array();    /**
     * RpcClient constructor.
     */
    public function __construct($url)
    {        $this->urlInfo = parse_url($url);
    }    /**
     * User: yuzhao
     * CreateTime: 2018/11/16 上午12:2
     * Description: 前往以后工具
     */
    public static function instance($url) {        return new RpcClient($url);
    }    public function __call($name, $arguments)
    {        // TODO: Implement __call() method.
        //创立一个客户端
        $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);        if (!$client) {            exit("{$errno} : {$errstr} \n");
        }
        $data = [            'class'  => basename($this->urlInfo['path']),            'method' => $name,            'params' => $arguments
        ];        //向效劳端发送咱们自界说的协定数据
        fwrite($client, json_encode($data));        //读取效劳端传来的数据
        $data = fread($client, 2048);        //封闭客户端
        fclose($client);        return $data;
    }
}
$cli = new RpcClient('http://127.0.0.1:8888/test');echo $cli->tuzisir1()."\n";echo $cli->tuzisir2(array('name' => 'tuzisir', 'age' => 23));

提供效劳的文件

<?php/**
 * User: yuzhao
 * CreateTime: 2018/11/16 上午12:28
 * Description:
 */class Test {    public function tuzisir1() {        return '我是无参办法';
    }    public function tuzisir2($params) {        return $params;
    }
}

成果

8758965292a1186e13410a9add29bd1.png

7.RPC的留意事项

功能:影响RPC功能的次要正在几个方面:
1.序列化/反序列化的框架
2.网络协定,网络模子,线程模子等

平安
RPC平安的次要正在于效劳接口的鉴权以及拜访管制支持。

跨平台
跨没有同的操作零碎,没有同的编程言语战争台。

以上就是php rpc怎样完成?的具体内容,更多请存眷资源魔其它相干文章!

标签: php开发教程 php开发资料 php开发自学 php rpc

抱歉,评论功能暂时关闭!