RPC全称为Remote Procedure Call,翻译过来为"远程过程调用"。主要应用于不同的系统之间的远程通信和相互调用。

比如有两个系统,一个是PHP写的,一个是JAVA写的,而PHP想要调用JAVA中的某个类的某个方法,这时候就需要用到RPC了。

怎么调?直接调是不可能,只能是PHP通过某种自定义协议请求JAVA的服务,JAVA解析该协议,在本地实例化类并调用方法,然后把结果返回给PHP。

这里我们用PHP的socket扩展来创建一个服务端和客户端,演示调用过程。

RpcServer.php代码如下:

<?php
class RpcServer {
protected $serv = null; public function __construct($host, $port, $path) {
//创建一个tcp socket服务
$this->serv = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr);
if (!$this->serv) {
exit("{$errno} : {$errstr} \n");
}
//判断我们的RPC服务目录是否存在
$realPath = realpath(__DIR__ . $path);
if ($realPath === false || !file_exists($realPath)) {
exit("{$path} error \n");
} while (true) {
$client = stream_socket_accept($this->serv); if ($client) {
//这里为了简单,我们一次性读取
$buf = fread($client, 2048);
//解析客户端发送过来的协议
$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]);
$file = $realPath . '/' . $class . '.php';
//判断文件是否存在,如果有,则引入文件
if(file_exists($file)) {
require_once $file;
//实例化类,并调用客户端指定的方法
$obj = new $class();
//如果有参数,则传入指定参数
if(!$paramsRet) {
$data = $obj->$method[1]();
} else {
$data = $obj->$method[1](json_decode($params[1], true));
}
//把运行后的结果返回给客户端
fwrite($client, $data);
}
} else {
fwrite($client, 'class or method error');
}
//关闭客户端
fclose($client);
}
}
} public function __destruct() {
fclose($this->serv);
}
} new RpcServer('127.0.0.1', 8888, './service');

RpcClient.php代码如下:

<?php

class RpcClient {
protected $urlInfo = array(); public function __construct($url) {
//解析URL
$this->urlInfo = parse_url($url);
if(!$this->urlInfo) {
exit("{$url} error \n");
}
} public function __call($method, $params) {
//创建一个客户端
$client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
if (!$client) {
exit("{$errno} : {$errstr} \n");
}
//传递调用的类名
$class = basename($this->urlInfo['path']);
$proto = "Rpc-Class: {$class};" . PHP_EOL;
//传递调用的方法名
$proto .= "Rpc-Method: {$method};" . PHP_EOL;
//传递方法的参数
$params = json_encode($params);
$proto .= "Rpc-Params: {$params};" . PHP_EOL;
//向服务端发送我们自定义的协议数据
fwrite($client, $proto);
//读取服务端传来的数据
$data = fread($client, 2048);
//关闭客户端
fclose($client);
return $data;
}
} $cli = new RpcClient('http://127.0.0.1:8888/test');
echo $cli->hehe();
echo $cli->hehe2(array('name' => 'test', 'age' => 27));

然后分别运行上面两个脚本(注意,php要添加环境变量)

> php RpcServer.php
> php RpcClient.php

结果如下:

Test.php代码如下:

<?php
class Test {
public function hehe() {
return 'hehe';
}
public function hehe2($params) {
return json_encode($params);
}
}

目录结构如下:

上面我们自定义的协议,可以随意修改,只要是客户端和服务端两边能够统一并能解析。

客户端通过请求服务端,把要调用的类,方法和参数传递给服务端,服务端去通过实例化调用方法返回结果。

使用PHP来简单的创建一个RPC服务的更多相关文章

  1. 从零开始基于go-thrift创建一个RPC服务

    Thrift 是一种被广泛使用的 rpc 框架,可以比较灵活的定义数据结构和函数输入输出参数,并且可以跨语言调用.为了保证服务接口的统一性和可维护性,我们需要在最开始就制定一系列规范并严格遵守,降低后 ...

  2. 使用PHP创建一个socket服务端

    与常规web开发不同,使用socket开发可以摆脱http的限制.可自定义协议,使用长连接.PHP代码常驻内存等.学习资料来源于workerman官方视频与文档. 通常创建一个socket服务包括这几 ...

  3. 为MongoDB创建一个Windows服务

    一:选型,根据机器的操作系统类型来选择合适的版本,使用下面的命令行查询机器的操作系统版本 wmic os get osarchitecture 二:下载并安装 附上下载链接 点击安装包,我这里是把文件 ...

  4. 【LINUX】——linux如何使用Python创建一个web服务

    问:linux如何使用Python创建一个web服务? 答:一句话,Python! 一句代码: /usr/local/bin/python -m SimpleHTTPServer 8686 > ...

  5. ng 通过factory方法来创建一个心跳服务

    <!DOCTYPE html> <html ng-app="myApp"> <head lang="en"> <met ...

  6. C# 创建一个WCF服务

    做代码统计,方便以后使用: app.config配置文件设置: <configuration> <system.serviceModel> <bindings> & ...

  7. 使用Quartz Job 简单的做一个定时服务

    第一步:创建一个windows服务 第二步:通过NuGet 安装Quartz (我搜索了Quartz 关键字 安装了 ) 第三步 代码部分 任务类 如 多个任务 就多几个类 public class ...

  8. 通过 Netty、ZooKeeper 手撸一个 RPC 服务

    说明 项目链接 微服务框架都包括什么? 如何实现 RPC 远程调用? 开源 RPC 框架 限定语言 跨语言 RPC 框架 本地 Docker 搭建 ZooKeeper 下载镜像 启动容器 查看容器日志 ...

  9. gRPC创建Java RPC服务

    1.说明 本文介绍使用gRPC创建Java版本的RPC服务, 包括通过.proto文件生成Java代码的方法, 以及服务端和客户端代码使用示例. 2.创建生成代码工程 创建Maven工程,grpc-c ...

随机推荐

  1. Logstash收集nginx日志之使用grok过滤插件解析日志

    grok作为一个logstash的过滤插件,支持根据模式解析文本日志行,拆成字段. nginx日志的配置: log_format main '$remote_addr - $remote_user [ ...

  2. LeetCode OJ 215. Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  3. [PC]PHPCMS二次开发指南(上)

    ------------------------------------------------------------------------------------- PHPCMS本身功能已经很完 ...

  4. [C语言]逆序的三位数

    ---------------------------------------------------------------------------------------- //  main.c ...

  5. Webservice之axis

    根据wsdl的url,使用axis1.4生成客户端,并且对webservice进行调用   1.到www.apache.org上去下载axis-bin-1_4.zip,如要关联源代码就把axis-sr ...

  6. python 小整数池 和intern 【整理】

    小整数对象池 (在python内置了) 整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池,避免为整数频繁申请和销毁内存空间. Python对小整数的定义是[-5,257]这些整 ...

  7. Oracle 查询版本号

    select * from v$version; -- 或 select banner from sys.v_$version;

  8. Oracle数据库操作总是显示运行中无法成功,删除表时报错 resource busy and acquire with NOWAIT specified

    1.直接运行以下语句: select t2.username,t2.sid,t2.serial#,t2.logon_timefrom v$locked_object t1,v$session t2wh ...

  9. SAP 优缺点

    1.优点: SAP是全球所有ERP产品中对企业构架和财务控制考虑得最细致的系统,也是整体控制逻辑和整体系统结构是最严谨的系统,可以让企业引进先进的管理理念: 对产品在各种行业的适用性考虑得最多的系统, ...

  10. 用python来分割图片

    程序思路: 此次程序主要是利用PIL(Python Image Libraty)这库,来进行图片的处理.PIL是一个功能非常强大的python图像处理标准库,但由于PIL只支持python2.7.如今 ...