1、简介

  这篇文章将会用最直白的方式介绍RPC,以及实现RPC客户端的Ajax跨域调用的例子。

  RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

  RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。

  以上来自度娘!看完上面明白什么是RPC么,在心中能将RPC整个服务过程构造出来么?当然不能啦,对于我们这种小白来说最好是用最直白的语言进行描述。

  从字面上我们是大概了解到是从一个服务器中调用另一个服务器中的方法,使用它提供的功能。在我最开始接触RPC的时候,是在这本书中《PHP精粹:编写高效PHP代码》【(美)Lorna Mitchell,(美)Davey Shafik,(美)Matthew Turland著;彭冲,胡琳译】。是的,我所从事的语言就是世界上最好的语言--PHP,222333哈哈。

  在这本书中所介绍的RPC的实现方式是通过HTTP协议进行的。但是当我在寻找相关资料的时候,已看其他语言的例子,咋不一样的咧,难道PHP就是独特的?RPC即是远程调用,一般来说是不关语言层面的呀!

  的确,RPC=Remote Produce Call 是一种技术的概念名词它可以通过不同的方式实现。http是rpc实现的一种方式,RPC还可以通过Socket自己实现一套协议来实现。当然啦,不同的实现方式有不同的特点,长短连接、数据的传输方式、灵活性等等。

  RPC的核心并不在于使用什么协议。RPC的目的是让你在本地调用远程的方法,而对你来说这个调用是透明的,你并不知道这个调用的方法是部署哪里。通过RPC能解耦服务,这才是使用RPC的真正目的。

RPC(远程过程调用)是什么

  • 简单的说,RPC就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。
  • RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯)
  • RPC 是一个请求响应模型。客户端发起请求,服务器返回响应(类似于Http的工作方式)
  • RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)

  即能够调用远程规定好的接口就可称之为RPC!在我上一篇文章中所讲的Web service(SOAP)也是RPC的一种实现方式。

  Thrift ,这是我最近学习的一个RPC框架,它很强大,数据是通过二进制格式进行传输,相对 XML 和 JSON 体积更小,对于高并发、大数据量和多语言的环境更有优势。当然啦,这里不讲这个RPC框架,毕竟刚接触,对于Thrift这方面的知识还是菜鸟级别。能懂一丢丢但是距离将它写成博客文章还是差很远的。

  接下来我将采用HTTP方式来实现一个RPC,并且在客户端中能够在Ajax下进行跨域访问。

2、PRC实例

  环境介绍:www.test88.com作为服务主机、www.test99.com作为客户端主机

  一个好的api可以支持不同的格式输出、大多RPC采用post方式提交数据!接下来我们将采用json格式输出、POST提交数据

  2.1、先建立具体服务功能的逻辑程序

  WebServer.class.php【www.test88.com】

 <?php
class WebServer
{
public static function test($name,$age,$action)
{
return $name.',今年年龄'.$age.',最喜欢做的事情是'.$action;
}
public static function look()
{
return $_POST;
}
public static function nono()
{
return '啥鸡毛都没有';
}
}
?>

  2.2、服务端提供相应的入口

  WebServer.php【www.test88.com】

  返回数据使用json格式!一个最基本的RPC服务已经建成!

 <?php
require './WebServer.class.php';
if(isset($_POST['method']))
{
$post=$_POST;
switch ($_POST['method']) {
case 'test':
$respond=WebServer::test($post['name'],$post['age'],$post['action']);
break;
case 'look':
$respond=WebServer::look();
break;
default:
$respond=WebServer::nono();
break;
}
}
else
{
$respond='木有!';
}
header('content-type:application/json');
echo json_encode($respond);
#echo $respond;
?>

  2.3、建立跨域代理脚本

  跨域请求解决:为避免同源策略,可使用服务器端代理即写个代理脚本放入自己的域中,使用ajax来访问代理脚本,脚本远程访问api接收数据,再将数据返回给需要的地方(好处:可是在代理的时候将接收回来的数据进行相应的数据类型结构处理,再返回需要的地方)

  Agency.class.php【www.test99.com】

 <?php
class Agency
{
#允许访问的api域名、返回的数据类型
public $allowHost=array('test88.com'=>array('mimetype'=>'aplication/json'));
public $host=''; public function __construct()
{
$this->host=parse_url("http:/".$_SERVER['PATH_INFO'],PHP_URL_HOST); #提取域名参数
} /**
* @desc 设置允许去访问的主机域名
*
* @param $host string 域名
* @param $array array 数组,放回的数据类型
*/
public function setAllowHost($host, $array=array('mimetype'=>'aplication/json'))
{
$this->allowHost[$host]=$array;
} /**
* @desc 判断域名
*
* @param $host string 域名
*/
private function decide($host)
{
if(!isset($this->allowHost[$host])) #判断host是否允许代理访问
{
header("Status:403 Forbidden");
exit;
}
return true;
} public function requestPost()
{
$host=$this->host;
$this->decide($host); #判断
$host='www.'.$host; //拼接host
$uri=strrchr($_SERVER['PATH_INFO'],'/'); #提取具体URI
$port=80;
$link=fsockopen($host,$port);
//请求行
#$request_data="POST /WebServer.php HTTP/1.1\r\n";
$request_data="POST $uri HTTP/1.1\r\n";
//请求头
#$request_data.="Host: www.test88.com\r\n";
$request_data.="Host: $host\r\n";
$request_data.="User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0\r\n";
$request_data.="Connection: keep-alive\r\n";
#post数据
#$post_data=array('name'=>$_POST['name'],'ff'=>'bbb');
$post_content=http_build_query($_POST);
$len=strlen($post_content);
$request_data.="Content-Length: ".$len."\r\n";
$request_data.="Content-Type: application/x-www-form-urlencoded\r\n"; $request_data.="\r\n"; //空行表示头结束 //请求主体
$request_data.=$post_content; //发送数据
fwrite($link,$request_data); //接收数据
$inheader=1;
while(!feof($link))
{
#echo fgets($link,1024);
//除去请求头,只显示返回数据
$data=fgets($link,1024);
if($inheader && ($data=="\n" || $data=="\r\n"))
{
$inheader=0;
}
if($inheader==0)
{
var_dump(json_decode($data));
echo ($data); #用于测试
}
}
//关闭请求
fclose($link);
} }

  实例化脚本:agency.php【www.test99.com】

 <?php
include "./Agency.class.php";
$a=new Agency();
$a->requestPost();
?>

  2.4、Ajax访问

  建立相应的html文件

  button.html【www.test99.com】

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>button</title>
</head>
<body>
<button id='b1'>按钮1</button>
</body>
<script type="text/javascript">
var b1=document.getElementById('b1');
b1.onclick=function()
{
var xhr=new XMLHttpRequest();
xhr.onreadystatechange=function()
{
if(xhr.readyState==4)
{
//document.body.innerHTML+=xhr.responseText;
alert(xhr.responseText)
}
}
//代理文件+(需要访问的api的域名+api具体的某个接口)
xhr.open('post','./agency.php/test88.com/WebServer.php');
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded');
//api接口参数使用info来传递
var info='method=look&name=小明&age=20&action=打架'; //相应参数
xhr.send(info);
}
</script>
</html>

  2.5、开始测试

  访问www.test99.com/button.html

  并点击按钮1

  

    

  更改访问方法method=test,继续访问

大功告成!

3、总结

  总的来说,我所写的这个例子是非常非常简单的,仅仅只是用来参考哈。当然啦,性能上肯定是鸡肋。在我自己做简单测试的时候,Ajax刷新返回数据都非常缓慢。对于小白的我们来说,结合一个简单实用的例子来学习了解一门技术还是不错的!希望大家对RPC的学习不要止步于此哈,毕竟我这篇博客是入门级的,更多相关的RPC知识还等着大家去挖掘呢!

(以上是自己的一些见解,若有不足或者错误的地方请各位指出)

作者:那一叶随风   http://www.cnblogs.com/phpstudy2015-6/

原文地址:http://www.cnblogs.com/phpstudy2015-6/p/6850658.html

声明:本博客文章为原创,只代表本人在工作学习中某一时间内总结的观点或结论。转载时请在文章页面明显位置给出原文链接

我对RPC的理解的更多相关文章

  1. 对hadoop之RPC的理解

    因为公司hadoop集群出现了一些瓶颈,在机器不增加的情况下需要进行优化,不管是存储还是处理性能,更合理的利用现有集群的资源,所以来学习了一波hadoop的rpc相关的知识和hdfs方面的知识,以及y ...

  2. 简单RPC之Socket实现

    最近看到Dubbo大神写得使用Socket实现的简单的RPC调用,对RPC的理解更简单了,然后根据大神的代码自己也重构了一下. RPC Server端代码,主要是使用ServerSocket获得rpc ...

  3. RabbitMQ、RPC、SaltStack "贡"具的使用

    消息队列 使用队列的场景 在程序系统中,例如外卖系统,订单系统,库存系统,优先级较高 发红包,发邮件,发短信,app消息推送等任务优先级很低,很适合交给消息队列去处理,以便于程序系统更快的处理其他请求 ...

  4. 微服务7:通信之RPC

    ★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...

  5. unity中的[xxxxxx]特性(Attributes)

    [SerializeField] 在Inspector版面中显示非public属性,并且序列化:若写在public前面,等于没写. [Obsolete("调用提示信息")] [No ...

  6. 阿里巴巴Java开发手册———个人追加的见解和补充(一)

    先上干货,<阿里巴巴Java开发手册>的下载地址 https://yq.aliyun.com/articles/69327?spm=5176.100239.blogcont69327.15 ...

  7. 阿里Java面经大全(整合版)

    本文里的面经内容全部来源于牛客网,作为秋招备战复习与查缺补漏时使用.里面部分面经有我的注释和想法,以及部分解答,不一定正确,大家可以查询补充. 阿里巴巴,三面,java实习 昨天晚上11点打电话来,问 ...

  8. hadoop17---RPC和Socket的区别

    RPC是在Socket的基础上实现的,它比socket需要更多的网络和系统资源.RPC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台 ...

  9. hadoop-2.3.0-cdh5.1.0完全分布式集群配置HA配置

    一.安装前准备: 操作系统:CentOS 6.5 64位操作系统 环境:jdk1.7.0_45以上,本次采用jdk-7u55-linux-x64.tar.gz master01 10.10.2.57  ...

随机推荐

  1. RunTime 给类添加属性

    RunTime网上有很多人都不知道Runtime到底是干嘛的?有很多博主都是长篇大论给他们讲这个讲那个,我感觉还不如实例来的实在.很简单的一个例子:我们都知道会有这样的需求,未读消息列表的图片上要有一 ...

  2. WebServiceWSDLWeb

    WSDL 文档仅仅是一个简单的 XML 文档. 它包含一系列描述某个 web service 的定义. WSDL 文档是利用这些主要的元素来描述某个 web service 的: 元素 定义 < ...

  3. 前端总结·基础篇·JS(四)异步请求及跨域方案

    前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...

  4. (转)Java ConcurrentModificationException异常原因和解决方法

    转载自:http://www.cnblogs.com/dolphin0520/p/3933551.html 在前面一篇文章中提到,对Vector.ArrayList在迭代的时候如果同时对其进行修改就会 ...

  5. 微信端解决a标签链接 失效的问题

    最近常碰到这个问题就是 在微信端点击a标签链接的时候,第一次正常界面跳转.但是,界面重新跳转回来再次点击a标签的话 .出现 界面不跳转,但是进度条加载完毕,点击多次页面无法跳转. 解决办法 在链接后边 ...

  6. C++命名空间【转】

    本讲基本要求 * 掌握:命名空间的作用及定义:如何使用命名空间.     * 了解:使用早期的函数库 重点.难点     ◆命名空间的作用及定义:如何使用命名空间.     在学习本书前面各章时,读者 ...

  7. maven私服搭建nexus介绍(二)

    1.各个仓库介绍 Hosted:宿主仓库 主要放本公司开发的SNAPSHOTS测试版本,RELEASES正式发行版.合作公司第三方的jar包. Proxy:代理仓库 代理中央仓库:代理Apache下测 ...

  8. sublime前端开发工具常用技巧

    ctrl+N//新建文件夹ctrl+shift+p//打开命令行!,ctrl+E//快速生成html模板ctrl+E//自动补齐ctrl+P(#@)//goto 任何地方,其中#查找元素,@查找样式c ...

  9. folly教程系列之:future/promise

         attension:本文严禁转载. 一.前言 promise/future是一个非常重要的异步编程模型,它可以让我们摆脱传统的回调陷阱,从而使用更加优雅.清晰的方式进行异步编程.c++11中 ...

  10. Java 别名(Aliasing)

    别名 (Aliasing) 别名,顾名思义,是有别于现在名字的另一个名字,但指的是不是同一个人或事物呢?比如,你上学的时候同学有没有给你起什么外号?如果有的话,你的名字和同学给你起的外号是不是都指的是 ...