这两天有人问我关于RPC的问题,这其实是一个很“古老”的概念。没有经历过DCOM和RMI开发时代的同学,可能对RPC的来龙去脉没有直观的认识。之前写过一篇文章,做了一个旁白,今天再发一次,希望能解决一些人的疑惑!我是一个函数,住在内存里,我的家——在你的“黑话”里——是进程的地址空间,而我的邻居也是一个函数,里面有一段很有意思的代码。我经常去看他。当然,我不能空手而归。我会带四个数作为礼物给他计算,耐心等他在CPU里干活半天。最后,作为回礼,他告诉了我一个地址,让我去那里拿结果。随着访问次数的增加,我慢慢弄清楚了我的邻居是做什么的:抵押贷款计算。我给他发的四个参数分别是房贷总额、利率、贷款期限、还款方式(等额本息为1,等额本金为2)。他告诉我的是一个地址,实际上是一个列表。每月还款,本息。在你的“黑话”里,是这样的:ListcalculateHouseLoan(floattotal,floatintrestRate,intyears,intloanType)所有的调用都发生在本地机器的一个进程中,大家都把这个方法称为本地过程调用。这种调用方式速度之快,眨眼之间就可以完成。有时候,算房贷的邻居会惊呼:“不好意思,你发给我的数字,一共八百万!我就知道,帝都的房价又涨了!日复一日,房价也是连日上涨,一天早上睡着了醒来感觉怪怪的头晕,一般是昨晚系统重启了。在我醒来之前,我收到了老板的命令(调用我的函数)重新计算抵押贷款。我忍着头晕赶紧去找邻居,这回来的是个陌生人,他笑着说:“你是在找邻居的房贷算盘吗?””“是”“他搬走了!“啊?他搬到哪里去了?房贷怎么算?”“他搬到了另一台机器Stop,具体位置我也不知道,不过从IP来看,应该是在同一个机房??。”说实话,这个消息让我很吃惊。之前听人说,如果要在网络上和一台机器通信,就比得上这台机器。同一个进程内的通信太麻烦了。我们住在和之前一样的流程,每个函数的地址(address)都是大家可见的,如果要调用,直接到函数的地址去执行代码就可以了,现在这个函数已经搬走了,我不'知道新地址,但是我知道。对于跨域网络调用,说的是应该使用什么套接字建立连接。在连接上,按照双方协商好的格式和顺序发送数据,以及receive数据听上去很头疼,打死也搞不定。(老刘自己变码农注:socket的故事可以参考《张大胖和socket》)陌生人看了我着急笑着说:“别担心,我是他的客户代理,给四个参数就行了给我,我帮你解决。”这个自称代理客户的家伙,居然知道四大参数!也许可行,但对我来说,调用方式并没有改变,所以我半信半疑,还是像以前一样传了四个参数。过去他立马忙起来,建立连接,发送数据,接收数据,过了很久(感觉比平时慢了100倍)他说抵押已经算好了,数据在地址XXXX,你去拿吧。我去那个地方查看,和往常一样,每月的还款结果都整齐地显示在那里。“你这个计算抵押的clientagent还真不含糊,既然是clientagent,那你有serveragent吗?””是的,我有一个做服务器端的好朋友,他约定了报文的格式,而我实际上是通过socket把你给我的数据发给他,他调用真正的抵押计算,然后发送返回结果。”“这就是传说中的远程进程调用(RPC)吗?”我问“是的,我们两个代理为您做了肮脏的工作,隐藏了那些复杂的网络细节,这与您眼中的本地电话不同。相同。对了,有些人会叫我Stub和我的好朋友Skeleton。我和他之间的交互是通过sockets。有些RPC代理可能不会用到这么底层的东西,直接用HTTP。不过没关系,只要两端代理同意就行,关键是给你一个舒服的体验。”“我想到一个问题,如果我传给你的不是简单的float或者int参数,而是内存中的一个对象,怎么处理呢?”“当然要序列化了,不然怎么传通过网络,其实float和int也需要序列化,把内存中的值和对象变成二进制流,这样才能发送出去。说到我的好朋友,他要做反序列化,把二进制流转成对象,然后调用真正的函数。唉,这工作真是麻烦。“我对他表达了深切的同情和敬意,为了让我们能够做到透明的远程通话,这些代理真的很不容易。”听说XML和JSON也可以用?”我问,“你知道的多吗?!有些人在使用HTTP作为通信协议的时候,喜欢把对象变成文本,比如XML/JSON,这样可读性更好,但是你要知道,HTTP在应用层虽然看起来像文本,但是在底层channel比如TCP发送出去,要转成二进制流,到目的地再转成文本。”(老刘注:参加《序列化:一个老家伙的咸鱼翻身》)聊了半天,我们越来越熟了,无意中说起他的身世。他说:“我们特工,出生方式主要有两种。一是程序员一行行代码把我们敲出来,细心费力,二是自动生成。》《自动生成,怎么做?》以Java为例,可以先定义一个接口(interface),让这个接口扩展自java.rmi.Remote,然后写一个实现类,最后使用一个工具rmic然后就可以自动生成客户端和服务器端代理了,是不是很简单?(注:从JDK5开始,客户端代理可以下载到客户端。)网络世界远比单机精彩。不知不觉中,我已经和这个代理聊了将近800毫秒。我的老板等不及了。他抱怨道:“这次怎么这么慢?这里加断点了吗?”我说:“没有调试,以前是本地过程调用,现在是远程过程调用!”coderising获取授权】点这里阅读更多作者的好文章作者
