最近在学习go时,看到微服务rpc时,在想php能不能实现呢,答案是肯定的,下面写下来记录一下。

先看目录结构
rpc
----api
--------Test.php
----client
--------RpcClient.php
--------RpcJsonClientGo.php
----server
--------RpcServer.php

1、外面先实现php的rpc服务

RpcServer.php

<?php/*** Rpc服务端*/
class RpcServer
{/*** 此类的基本配置*/private $params = ['host' => '',  // ip地址,列出来的目的是为了友好看出来此变量中存储的信息'port' => '', // 端口'path' => '' // 服务目录];/*** 本类常用配置*/private $config = ['real_path' => '','max_size' => 2048 // 最大接收数据大小];private $server = null;/*** Rpc constructor.*/public function __construct($params){$this->check();$this->init($params);}/*** 必要验证*/private function check(){$this->serverPath();}/*** 初始化必要参数*/private function init($params){// 将传递过来的参数初始化$this->params = $params;// 创建tcpsocket服务$this->createServer();}/*** 创建tcpsocket服务*/private function createServer(){$host = $this->params['host'] ?? '';$port = $this->params['port'] ?? 8081;if(empty($host)){exit('host error');}$this->server = stream_socket_server("tcp://{$host}:{$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;}/*** 返回当前对象*/public static function instance($params){return new RpcServer($params);}/*** 运行*/public function run(){echo "开始服务......\n";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";}}}/*** 执行方法* @param $class* @param $method* @param $params*/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');}}/*** 解析协议*/private function parseProtocol($buf, &$class, &$method, &$params){$buf = json_decode($buf, true);$class = $buf['class'];$method = $buf['method'];$params = $buf['params'];}/*** @param $data* 打包协议*/private function packProtocol(&$data){$data = json_encode($data, JSON_UNESCAPED_UNICODE);}}RpcServer::instance(['host' => '127.0.0.1','port' => 8081,'path' => '../api'
])->run();

Test.php

<?phpclass Test
{public function testString(){return '测试字符串方法';}public function testParams($params){return $params;}public function getName(){return 'hello word ' ;  // 返回字符串}
}

2、在写客户端

RpcClient.php

<?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){//创建一个客户端$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;}
}$client = new RpcClient('http://127.0.0.1:8081/test');
echo $client->testString() . "\n";
echo $client->testParams(array('name' => 'tuzisir', 'age' => 23));

查看运行结果

下面跨语言连接Go的jsonrpc服务

RpcJsonClientGo.php

<?phpclass RpcJsonClientGo
{private $conn;function __construct($host, $port){$this->conn = fsockopen($host, $port, $errno, $errStr, 3);if (!$this->conn) {return false;}}public function Call($method, $params){// 检验request信息if (!is_scalar($method)) {return "Method name has no scalar value";}if (!$this->conn) {return false;}$err = fwrite($this->conn, json_encode(['method' => $method,'params' => array($params),'id' => 0,]) . "\n");if ($err === false) {return false;}stream_set_timeout($this->conn, 0, 3000);$line = fgetc($this->conn);if($line === false){return null;}return json_decode($line,true);}}$client = new RpcJsonClientGo("127.0.0.1",8080);
echo $client->Call(['ddd'=>22], "this is php languages");

执行php客户端文件,在go服务端就能看到发送来的数据

php 实现rpc,使用php链接jsonrpc服务相关推荐

  1. 阿里P8架构师谈:Restful、SOAP、RPC、SOA、微服务之间的区别

    内容大纲: 1.介绍Restful.SOAP.RPC.SOA以及微服务 2.重点谈谈SOA与微服务的区别 3.以及为什么要使用微服务架构 什么是Restful Restful是一种架构设计风格,提供了 ...

  2. Restful、SOAP、RPC、SOA、微服务之间的区别

    一.介绍Restful.SOAP.RPC.SOA以及微服务 1.1.什么是Restful? Restful是一种架构设计风格,提供了设计原则和约束条件,而不是架构,而满足这些约束条件和原则的应用程序或 ...

  3. golang解析IP到城市jsonRPC服务教程

    RESTful接口 请求URL: https://api.xxx.com/Tbsapi/v1/ip2addr?ip=219.140.227.235 请求方式: GET 参数: 参数名 类型 说明 ip ...

  4. geoip mysql_使用geoIP数据库解析IP到城市jsonRPC服务教程

    ### RESTful接口 **请求URL:** - ` https://api.turboes.com/Tbsapi/v1/ip2addr?ip=219.140.227.235` **请求方式:** ...

  5. fguillot json rpc_Hyperf 框架创建 JSON-rpc 服务

    我们创建一个User服务供其他服务调用以实现认证和鉴权. checkToken 方法接收两个参数,一个token,一个permission,首先验证token获得user,对user的鉴权将在以后的权 ...

  6. 分布式链接跟踪服务_微服务世界中的分布式跟踪

    分布式链接跟踪服务 微服务已成为未开发应用程序的默认选择. 毕竟,从业人员认为,微服务提供了完全数字化转型所需的解耦类型,从而使各个团队的创新速度比以往任何时候都快. 微服务只不过是常规的分布式系统, ...

  7. RPC原来就是Socket——RPC框架到dubbo的服务动态注册,服务路由,负载均衡演化...

    序:RPC就是使用socket告诉服务端我要调你的哪一个类的哪一个方法然后获得处理的结果.服务注册和路由就是借助第三方存储介质存储服务信息让服务消费者调用.然我们自己动手从0开始写一个rpc功能以及实 ...

  8. RPC(管理端口的服务)NFS软件 NFS配置文件 简单介绍

    目录: 1什么是RPC(管理端口的服务) 2 NFS软件 3 NFS配置文件 1什么是RPC(管理端口的服务) 因为NFS支持的功能相当多,而不同的功能都会使用不同的程序来启动,每启动一个功能就会启用 ...

  9. 学习使用js链接websocket服务断线重连的方法

    学习使用js链接websocket服务断线重连的方法 前言 思路 示例代码 前言 我们在是有websocekt的时候,有的时候由于某些原先websocket会断开连接,我们需要重现连接,该如何实现呢? ...

  10. 【车载开发系列】UDS诊断---链接控制服务($0x87)

    [车载开发系列]UDS诊断-链接控制服务($0x87) 诊断---链接控制服务($0x87) [车载开发系列]UDS诊断---链接控制服务($0x87) 一.概念定义 二.应用场景 三.报文格式 1) ...

最新文章

  1. 使用python调用zabbix接口截取监控图并生成Word文档
  2. 关于解决多台linux服务器间的文件实时同步问题
  3. JS数组去重之利用set数据结构去重
  4. 深度学习帮助人工智能走得更远
  5. hdu 1692(枚举+剪枝)
  6. 2018-2019-1 20189201 《LInux内核原理与分析》第九周作业
  7. 学生群体中奖励制度的马太效应
  8. 北大OJ(POJ 2503)在线翻译
  9. JavaScript:class类的实现方式及特点
  10. 20.go vet 和 go tool vet
  11. Python3使用bencode库解析BT种子
  12. java 实现宠物领养_基于JavaEE的宠物领养系统的设计与实现任务书
  13. Mac蓝牙无法使用怎么办?教你7个修复蓝牙的技巧
  14. 计算机与调制解调器之间接口为,单片机串行接口和调制解调器如何实现远程通信...
  15. 虚拟机ipv4和6都没访问权限_无线网络连接 ipv4/6都无网络访问权限该怎么解决
  16. 计算机在无法打开情况下怎么重置,电脑提示internet explorer无法打开internet站点怎么办...
  17. nodejs免安装版安装
  18. 几何画板如何添加按钮
  19. C语言:选列主元约当消元法求线性方程组唯一解
  20. 必知必会 | 音视频基础知识

热门文章

  1. Fedora Core下声卡驱动全功略(转)
  2. msm8953 单独编译bootloader、kernel和system,以及采用adb fastboot下载镜像的方法
  3. 关灯游戏 Lights out (二)(首行枚举+位运算,搜索全部解)
  4. 把栏杆拍遍--辛弃疾
  5. Axure RP 9.0.0.3716 Mac中文版
  6. 深挖那些隐藏在Linux中的炫酷主题
  7. 最全的数据结构和算法,不信过来看看有没有漏掉的
  8. 【Oracle】SQL查询 基本查询语句
  9. 无线通信行业常用名词
  10. Navicat 数据库可视化工具远程连接MySQL及基本操作