我对RPC的理解
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的理解的更多相关文章
- 对hadoop之RPC的理解
因为公司hadoop集群出现了一些瓶颈,在机器不增加的情况下需要进行优化,不管是存储还是处理性能,更合理的利用现有集群的资源,所以来学习了一波hadoop的rpc相关的知识和hdfs方面的知识,以及y ...
- 简单RPC之Socket实现
最近看到Dubbo大神写得使用Socket实现的简单的RPC调用,对RPC的理解更简单了,然后根据大神的代码自己也重构了一下. RPC Server端代码,主要是使用ServerSocket获得rpc ...
- RabbitMQ、RPC、SaltStack "贡"具的使用
消息队列 使用队列的场景 在程序系统中,例如外卖系统,订单系统,库存系统,优先级较高 发红包,发邮件,发短信,app消息推送等任务优先级很低,很适合交给消息队列去处理,以便于程序系统更快的处理其他请求 ...
- 微服务7:通信之RPC
★微服务系列 微服务1:微服务及其演进史 微服务2:微服务全景架构 微服务3:微服务拆分策略 微服务4:服务注册与发现 微服务5:服务注册与发现(实践篇) 微服务6:通信之网关 微服务7:通信之RPC ...
- unity中的[xxxxxx]特性(Attributes)
[SerializeField] 在Inspector版面中显示非public属性,并且序列化:若写在public前面,等于没写. [Obsolete("调用提示信息")] [No ...
- 阿里巴巴Java开发手册———个人追加的见解和补充(一)
先上干货,<阿里巴巴Java开发手册>的下载地址 https://yq.aliyun.com/articles/69327?spm=5176.100239.blogcont69327.15 ...
- 阿里Java面经大全(整合版)
本文里的面经内容全部来源于牛客网,作为秋招备战复习与查缺补漏时使用.里面部分面经有我的注释和想法,以及部分解答,不一定正确,大家可以查询补充. 阿里巴巴,三面,java实习 昨天晚上11点打电话来,问 ...
- hadoop17---RPC和Socket的区别
RPC是在Socket的基础上实现的,它比socket需要更多的网络和系统资源.RPC(Remote Procedure Call,远程过程调用)是建立在Socket之上的,出于一种类比的愿望,在一台 ...
- 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 ...
随机推荐
- Javascript 闭包访问问题?
function pfajax(paradata){ $.ajax({ data : paradata.dat, type : paradata.method, async: false, url : ...
- jQuery对象长度size
jQuery对象有两个方法获取其长度,一个是length属性,一个是调用size()方法,据说前者的效率比后者的高. 代码如下: var DQNRList=$("a[id^='DQNR']& ...
- Asp.NetCore之组件写法
本章内容和大家分享的是Asp.NetCore组件写法,在netcore中很多东西都以提供组件的方式来使用,比如MVC架构,Session,Cache,数据库引用等: 这里我也通过调用验证码接口来自定义 ...
- MySQL---连接器(python如何操作数据库媒介,基于python语言)
MySQL — 连接器 连接器的概念 它们往往是一类Python包,或者是一类已经写好的Python库.这些库提供了我们Python去连接数据库服务器的基本功能. 既然它是一个包,那么我们首先学会 ...
- MySQL读写分离技术
1.简介 当今MySQL使用相当广泛,随着用户的增多以及数据量的增大,高并发随之而来.然而我们有很多办法可以缓解数据库的压力.分布式数据库.负载均衡.读写分离.增加缓存服务器等等.这里我们将采用读写分 ...
- 倒排索引的AND操作
这是一道来自百度的面试题.倒排索引的AND操作. 倒排索引是以关键词作为索引项来索引文档的一种机制,如图中Brutus.Calpurnia.Caesar为关键词,2.4.8等等为文档ID. 现在有一个 ...
- Asp .Net MVC4笔记之走进MVC
一.MVC三层架构: mvc三层架构,大家都比较熟悉了,这里再介绍一下.Mvc将应用程序分离为三个部分: Model:是一组类,用来描述被处理的数据,同时也定义这些数据如何被变更和操作的业务规则.与数 ...
- 【shell编程基础0】bash shell编程的基本配置
前面一篇“shell编程之变量篇”主要讲述下shell编程的变量的基本知识:设置变量的方式,自定义变量和环境变量的差别,变量的替换.删除.测试等. 这一篇主要是讲述在bash shell下的一些基本配 ...
- Maven(二)之Maven项目构建演练
从上一篇的讲解中我们知道了什么是Maven,然后它的安装配置,到修改本地仓库,这篇我们用一个实际的例子,带领大家走进我们的Maven之旅.让我们一起来体验一下Maven的高度自动化构建项目的过程. 一 ...
- CSS清除float浮动
一.浮动产生原因 - TOP 一般浮动是什么情况呢?一般是一个盒子里使用了CSS float浮动属性,导致父级对象盒子不能被撑开,这样CSS float浮动就产生了. 本来两个黑色对象盒子是在 ...