我对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】

 1 <?php
 2 class WebServer
 3 {
 4     public static function test($name,$age,$action)
 5     {
 6         return $name.‘,今年年龄‘.$age.‘,最喜欢做的事情是‘.$action;
 7     }
 8     public static function look()
 9     {
10         return $_POST;
11     }
12     public static function nono()
13     {
14         return ‘啥鸡毛都没有‘;
15     }
16 }
17 ?>

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

  WebServer.php【www.test88.com】

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

 1 <?php
 2 require ‘./WebServer.class.php‘;
 3 if(isset($_POST[‘method‘]))
 4 {
 5     $post=$_POST;
 6     switch ($_POST[‘method‘]) {
 7         case ‘test‘:
 8             $respond=WebServer::test($post[‘name‘],$post[‘age‘],$post[‘action‘]);
 9             break;
10         case ‘look‘:
11             $respond=WebServer::look();
12             break;
13         default:
14             $respond=WebServer::nono();
15             break;
16     }
17 }
18 else
19 {
20     $respond=‘木有!‘;
21 }
22 header(‘content-type:application/json‘);
23 echo json_encode($respond);
24 #echo $respond;
25 ?>

  2.3、建立跨域代理脚本

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

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

 1 <?php
 2 class Agency
 3 {
 4     #允许访问的api域名、返回的数据类型
 5     public $allowHost=array(‘test88.com‘=>array(‘mimetype‘=>‘aplication/json‘));
 6     public $host=‘‘;
 7
 8     public function __construct()
 9     {
10         $this->host=parse_url("http:/".$_SERVER[‘PATH_INFO‘],PHP_URL_HOST); #提取域名参数
11     }
12
13     /**
14     * @desc 设置允许去访问的主机域名
15     *
16     * @param $host   string 域名
17     * @param $array  array  数组,放回的数据类型
18     */
19     public function setAllowHost($host, $array=array(‘mimetype‘=>‘aplication/json‘))
20     {
21         $this->allowHost[$host]=$array;
22     }
23
24     /**
25     * @desc 判断域名
26     *
27     * @param $host string 域名
28     */
29     private function decide($host)
30     {
31         if(!isset($this->allowHost[$host])) #判断host是否允许代理访问
32         {
33             header("Status:403 Forbidden");
34             exit;
35         }
36         return true;
37     }
38
39     public function requestPost()
40     {
41         $host=$this->host;
42         $this->decide($host);   #判断
43         $host=‘www.‘.$host;  //拼接host
44         $uri=strrchr($_SERVER[‘PATH_INFO‘],‘/‘); #提取具体URI
45         $port=80;
46         $link=fsockopen($host,$port);
47         //请求行
48         #$request_data="POST /WebServer.php HTTP/1.1\r\n";
49         $request_data="POST $uri HTTP/1.1\r\n";
50         //请求头
51         #$request_data.="Host: www.test88.com\r\n";
52         $request_data.="Host: $host\r\n";
53         $request_data.="User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0\r\n";
54         $request_data.="Connection: keep-alive\r\n";
55         #post数据
56         #$post_data=array(‘name‘=>$_POST[‘name‘],‘ff‘=>‘bbb‘);
57         $post_content=http_build_query($_POST);
58         $len=strlen($post_content);
59         $request_data.="Content-Length: ".$len."\r\n";
60         $request_data.="Content-Type: application/x-www-form-urlencoded\r\n";
61
62         $request_data.="\r\n"; //空行表示头结束
63
64         //请求主体
65         $request_data.=$post_content;
66
67         //发送数据
68         fwrite($link,$request_data);
69
70         //接收数据
71         $inheader=1;
72         while(!feof($link))
73         {
74             #echo fgets($link,1024);
75             //除去请求头,只显示返回数据
76             $data=fgets($link,1024);
77             if($inheader && ($data=="\n" || $data=="\r\n"))
78             {
79                 $inheader=0;
80             }
81             if($inheader==0)
82             {
83                 var_dump(json_decode($data));
84                 echo ($data);  #用于测试
85             }
86         }
87         //关闭请求
88         fclose($link);
89     }
90
91
92 }

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

1 <?php
2 include "./Agency.class.php";
3 $a=new Agency();
4 $a->requestPost();
5 ?>

  2.4、Ajax访问

  建立相应的html文件

  button.html【www.test99.com】

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta charset="utf-8">
 5     <title>button</title>
 6 </head>
 7 <body>
 8 <button id=‘b1‘>按钮1</button>
 9 </body>
10 <script type="text/javascript">
11 var b1=document.getElementById(‘b1‘);
12 b1.onclick=function()
13 {
14     var xhr=new XMLHttpRequest();
15     xhr.onreadystatechange=function()
16     {
17         if(xhr.readyState==4)
18         {
19             //document.body.innerHTML+=xhr.responseText;
20             alert(xhr.responseText)
21         }
22     }
23     //代理文件+(需要访问的api的域名+api具体的某个接口)
24     xhr.open(‘post‘,‘./agency.php/test88.com/WebServer.php‘);
25         xhr.setRequestHeader(‘content-type‘,‘application/x-www-form-urlencoded‘);
26         //api接口参数使用info来传递
27         var info=‘method=look&name=小明&age=20&action=打架‘;   //相应参数
28         xhr.send(info);
29 }
30 </script>
31 </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

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

时间: 2024-10-15 23:09:26

我对RPC的理解的相关文章

用Golang手写一个RPC,理解RPC原理

代码结构 . ├── client.go ├── coder.go ├── coder_test.go ├── rpc_test.go ├── server.go ├── session.go └── session_test.go 代码 client.go package rpc import ( "net" "reflect" ) // rpc 客户端实现 // 抽象客户端方法 type Client struct { conn net.Conn } // cl

服务之间的调用之RPC深入理解

一:RPC RPC 即远程过程调用(Remote Procedure Call Protocol,简称RPC),像调用本地服务(方法)一样调用服务器的服务(方法).通常的实现有 XML-RPC , JSON-RPC , 通信方式基本相同, 所不同的只是传输数据的格式. RPC是分布式架构的核心,按响应方式分如下两种: 同步调用:客户端调用服务方方法,等待直到服务方返回结果或者超时,再继续自己的操作 异步调用:客户端把消息发送给中间件,不再等待服务端返回,直接继续自己的操作. 同步调用的实现方式有

谈谈自己对rest和RPC的理解

一.什么是rest rest是一种架构风格,restful是遵循这种架构风格的应用程序或者设计.rest这种架构风格是美国一个博士在他的博士论文中提出来的,皆在于解决随着互联网的快速发展,传统的软件已经无法满足在这个时代背景下人们需求.在这个新的时代下,在这个万物互联的时代下,网络和软件这两个曾经单独存在的领域,已经无法在单独存在了,两者之间的交互和融合已经势在必行.rest架构风格就是在这样一个背景下被提出来的,他强调组件交互的可伸缩性.接口的通用性.组件的独立部署.以及用来减少交互延迟.增强

Hessian RPC示例和基于Http请求的Hessian序列化对象传输

本文主要介绍两个案例,第一个是使用Hessian来实现远程过程调用,第二个是通过Hessian提供的二进制RPC协议进行和Servlet进行数据交互,Hessian本身即是基于Http的RPC实现. 案例一: 1.准备工作 这里建立一个Maven项目,其中包含四个模块,父模块(仅用来聚合其它模块,不做实际使用),服务器端模块,客户端模块,API模块(远程过程接口,供服务器和客户端使用).目录结构见下图: 2.添加Hessian的依赖 由于客户端和服务器都要依赖Hessian的包,这里可以添加到父

RPC框架几行代码就够了

转载:http://javatar.iteye.com/blog/1123915#bc2395513 原作者为梁飞,dubbo的核心成员.本人认为这段代码不长,但是非常利于对RPC的理解,自己受益匪浅. java代码: 1 /* 2 * Copyright 2011 Alibaba.com All right reserved. This software is the 3 * confidential and proprietary information of Alibaba.com ("C

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

先上干货,<阿里巴巴Java开发手册>的下载地址 https://yq.aliyun.com/articles/69327?spm=5176.100239.blogcont69327.158.xUUgiz 下面分几个部分对这个手册进行说明,都是个人的见解,本人技术一般,如果有错误或者不妥,请评论指出,虚心接受,提前感谢了. 建议边看手册,边食用以下说明,效果比较好. 前言 首先当我第一次看见这个的手册的时候或许和和你们是一样激动的,因为在java行业内我还没有看见有中文的规范,也可能是我读书少

SerializeField等Unity内的小用法

[SerializeField] 在Inspector版面中显示非public属性,并且序列化:若写在public前面,等于没写……(至于序列化是啥,自行脑补……),上图: [NonSerialized]在Inspector版面中隐藏public属性,并且序列化:如果写在非public属性前面,等于没写……,上图: [HideInInspector] 在Inspector版面中隐藏public属性,与上面相比,只是隐藏,没有序不序列化的功能……,上图: [AddComponentMenu("XX

Unity一些属性的用法

[SerializeField] 在Inspector版面中显示非public属性,并且序列化:若写在public前面,等于没写……(至于序列化是啥,自行脑补……),上图: [NonSerialized]在Inspector版面中隐藏public属性,并且序列化:如果写在非public属性前面,等于没写……,上图: [HideInInspector] 在Inspector版面中隐藏public属性,与上面相比,只是隐藏,没有序不序列化的功能……,上图: [AddComponentMenu("XX

NFS网络文件系统原理及案例

从现在开始我决定把我所学的知识以博客的形式分享给大家,希望对和我一样的菜鸟,同时梦想成为一只老鸟的IT小伙伴有一定的帮助!而对于我而言,这本身也是一种学习呢!好了废话不多说,我们开始进入主题:我们人在接触一个新事物或者是一个新技一个新技术的时候,我们往往想到的第一个问题就是"这是什么呀?"或者"这是干什么的呀?"那么NFS网络文件系统到底是一个什么东西,它的作用又是什么,我们在这里围绕这两个问题进行讨论: 1.什么是NFS NFS是Network File Syst