咖啡馆的故事:FTP, RMI , XML-RPC, SOAP, REST一网打尽

开发
ftp老头儿满脸沧桑,喝了一口咖啡,说道:“简单得很,机器A通过我,就是ftp, 上传一个文件到机器B的指定路径,然后再让rexec 去调用机器B上的程序,这程序是程序员写的,可以读取FTP目录下的文件,执行业务逻辑就行了。”

 [[253832]]

周末的咖啡馆有点奇怪, 一群人围着几个老头儿在聊天。

“快说说,你们那个时候没有HTTP, 没有JavaScript,到底是怎么让这些机器上的程序进行'交谈'的?”

ftp老头儿满脸沧桑,喝了一口咖啡,说道:“简单得很,机器A通过我,就是ftp, 上传一个文件到机器B的指定路径,然后再让rexec 去调用机器B上的程序,这程序是程序员写的,可以读取FTP目录下的文件,执行业务逻辑就行了。”

 

“什么是rexec ? ”

“就是从一台机器上远程执行另外一个机器的命令嘛!” rexec老头儿略带怒气地说道,自己虽然没有ftp出名,但是不至于没人知道吧!

rexec [remote_host] [command]

“切!骗谁呢,根本不可能,怎么会用这么笨的方式!”人群中传来了表示不屑的声音。

ftp和rexec相视苦笑,这些程序员不会想到,早些年真有这么做的系统,是真实的故事。

ftp招呼telnet一起喝咖啡,不再出声。

RPC

门口传来一阵喧嚣,CORBA和Java RMI风风火火地走了进来。

人群呼啦一下子就围了上去,抛弃了那三个老头儿。

只听见Java RMI说道:“所有的程序本质上都是函数调用,函数调用在一个进程内是无比自然的事情。 如果是跨越机器、跨越进程呢? 如果一个机器上的函数,能调用另外一个机器上的函数,就像调用本地方法一样,会是什么样子? ”

CORBA笑着说:“哈哈, 画面太美不敢想象。 ”

人群中有人问道:“调用远程方法就像调用本地方法一样?怎么可能?”

Java RMI说道:“在概念上其实极其简单,无非就是自动生成客户端代理和服务器端代理,这两个代理完成了大量的脏活和累活,比如:网络通信,参数序列化...... ”

CORBA接着说道:“魔法都在这两个代理当中,我们称之为Stub(客户端代理)和Skeleton(服务器端代理)。这个Stub代理提供了和服务器一模一样的接口,客户端程序只要调用它,它就会把请求发到服务器端的Skeleton代理进行处理。 所以对于客户端程序来说,网络不可见,就像是调用本地的方法一样。”


 

Java RMI说道:“对,我们把这种方式称为RPC。”

人群中发出一片惊叹声:“这RPC可真好啊,Stub和Skeleton代码能自动生成,我们拿到以后,马上就可以动手编程了,底层什么都不用关心。 ”

Java RMI说道:“底层可以采用二进制的协议,性能不要太好哦!”

人群中又是一阵欢呼:“太好了!”

那边的ftp老头儿警告到:“大家要小心,要注意平台绑定,你想用Java RMI吗? 对不起,客户端和服务器都得用Java,都得安装Java虚拟机, 什么Python, C#, 没门儿, 连想都不要想。 ”

telnet接着说:“更重要的是客户端和服务器紧密绑定,服务器端的变化,都必须得重新生成Stub和Skeleton 。 ”

没想到这些老家伙们目光如炬。

“什么? 这也太无理了吧!” 人群呼啦一声又涌到了三个老头那里。

只见ftp老头儿在纸上写到: 比如说有这么一个接口, 可以根据用户ID查找用户信息。

  1. public interface UserService extends Remote{ 
  2.     public User findUser(int  id) throws RemoteException; 

利用Java RMI的工具,可以生成Stub和Skeleton, 客户端拿到Stub以后,可以开心地去编程了。

至于UserService的具体实现代码,客户端不用操心。

过了两天,某个客户端要求要给这个接口增加一个新的方法:按照名称来查找用户。

  1. public User findUser(String name) throws RemoteException; 

那对不起了,需要重新生成新的Stub和Skeleton, 所有的客户端都会受到影响,即使你根本不需要新的方法。

大家纷纷唉声叹气,这RPC实在是太烦人了!

有没有一种办法,让服务器端独立变化,而不影响客户端,或者说尽量不影响客户端呢?

XML-RPC

后面有个小伙字若有所思,他刚学会了XML, 他觉得既然XML的描述能力这么强,能不能用XML来描述一个方法调用和参数呢?

比如服务器端有个接口是getUser,需要提供的参数是用户ID, 可以这么描述:

 

然后通过HTTP Post把这个XML发送到服务器端,服务器端进行解析,获取方法名称和参数的值,调用真正的方法,把结果也以XML形式返回, 客户端收到以后再解析就可以得到结果了。

想到此处,他大声叫道:“别生成什么Stub和Skeleton代理了,直接用HTTP和XML该多好啊。”

人群被他的奇异想法所吸引,呼啦一下又围了过来。

小伙子画了一张图, 展示了这个处理的过程:

 

有人问道:“返回的数据格式可能很复杂, 怎么表示啊。”

小伙子说:“这正是XML的强项啊,图中展示的是int型,还可以有double ,boolean ,string 等各种类型,甚至可以定义结构体。”

 

对XML来说,这样的结构体就是小菜一碟。

“这样客户端和服务器端就变成松耦合的了,如果服务器端想添加一个新的接口,客户端就不用做变化了。我打算把他叫做XML-RPC” 小伙子说道。

“这种办法真好!” 人群中开始躁动起来,“我们都用XML-RPC吧!”

SOAP

“小伙子,你叫什么名字?” 狂热的人群中有个人冷静地问道。

“Dave Winer, 怎么了? ”

“Winner? 嗯,你的名字真不错,天生赢家啊, 有没有兴趣和我们微软一起制定一个新的RPC标准?”

“新标准? 我的XML-RPC已经很完善了,又简单又好用。”

“No,No, 还欠缺不少东西,最要命的就是客户端和服务器端没有正式的协议约定,都是口头约定,或者文档约定,对吧?”

Dave Winer点点头。

“你想想,如果我们把一个服务器对外提供的接口也用XML精确地描述下来,任何程序,只要读取这个XML文件,就知道接口的方法名,参数名,该有多好?”

Dave Winer又点点头。

“还有啊,你的XML-RPC只支持HTTP, 我们的新标准可以支持任意协议啊, HTTP, SMTP,TCP,UDP......都可以。”

“我还是觉得HTTP***!”

“想想看,如果我们的新协议搞成了,所有的B2B的电子商务系统都可以用这一套协议来自动通信,多么***的世界! 你仔细想想,你是想在这个破咖啡馆喝一辈子咖啡,还是想和我们微软一起改变世界?”

一年以后,Dave Winer 新的协议问世了,不,这其实是一套协议:

WSDL :用于描述一个服务的接口,参数......

UDDI : 实现服务的注册和发现

SOAP : 和XML-RPC很像,但是更加规范,更加正式,更加复杂......

他们之间的关系如图所示:

 

微软的.NET战略适时启动,Web Service的宣传铺天盖地:你只要用WSDL定义了接口,就可以选择任何语言来实现! Java , Python, 甚至C语言都可以,当然,我们的Visual Studo, C#和它结合得更好,欢迎使用。

人们趋之若鹜。

几年以后

Dave Winer又一次来到了咖啡馆,这一次他选择了一个角落坐下,要了一杯咖啡,静静地听大家聊天。

“你们知道吗,微软太坑爹了,那个SOAP实在是太难用了!”

“没错没错,罗嗦,罗嗦,太罗嗦了。你看看,我每次发个SOAP请求得多麻烦:”

  1. <?xml version="1.0"?> 
  2. <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:m="http://www.example.org"
  3.   <soap:Header> 
  4.   </soap:Header> 
  5.   <soap:Body> 
  6.     <m:GetUser> 
  7.       <m:UserID>1001</m:UserID> 
  8.     </m:GetUser> 
  9.   </soap:Body> 
  10. </soap:Envelope> 

“这算什么,返回值也是同样罗嗦的XML,解析起来实在是累死了。”

“是啊,如果没有可视化工具的辅助,简直是无法使用。”

Dave Winer一边喝咖啡一边想,没办法,这XML就是这样,不过我们的SOAP搞得是不是有点过分了?

“我觉得这就是那些大厂商们为了赚钱而搞出的东西,都是为了卖他们的软件,一点都不实用!”

“我们还是回归最简单的HTTP调用吧!” 有人提议。

比如想获取一个用户的信息,可以调用这样的API http://xxx.com/getUser?id=1001

“服务器端还要返回又臭又长的XML吗? ”

“不,我们可以用JSON这种数据格式,简洁紧凑,对JavaScript非常友好,处理起来非常方便。”

大家都表示同意。

“大家别激动,如果用这种方式,和原来的XML-RPC本质上是一样的,都是把服务器端看做是一堆函数的集合,然后客户端去调用他们。Java RMI是通过Stub/Skeleton代理的方式,XML-RPC是通过XML的方式。” 一个叫做罗伊的小伙提醒道。

 

“那可不咋地,服务器端不就是一堆函数吗?” 有人说道。

“大家转换一下思路,别把他们当成函数,当成资源(Resource), 从动词转换成名词试试。”

听到罗伊这新奇的想法,一群人又围了上来。

“名词? 资源? ”

“是啊,比如说用户,学生,订单等等。他们天然可以用uri来表示。”

 

“有点意思, 那对这些资源怎么操作?”

“HTTP的方法GET,POST, DELETE,PUT,HEAD...... 可以充当动词啊。”罗伊说道。

 

“我的妈啊,你竟然把HTTP的方法当成增删改查了。”

话虽这么说,可是大家都觉得这种方式挺简单的,充分利用了HTTP的特性,只要脑子里不要把服务器端看成函数,而是当作一堆名词资源就可以了。

“这种方式叫什么名字?”

“RESTful API !”

“这RESTful看起来不错啊,要不我们试试?”

“试试去!不行的话就找这个罗伊算账!”

【本文为51CTO专栏作者“刘欣”的原创稿件,转载请通过作者微信公众号coderising获取授权】

戳这里,看该作者更多好文

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2024-04-26 00:25:52

Rust语法生命周期

2021-08-05 06:54:05

流程控制default

2024-02-27 10:11:36

前端CSS@规则

2021-10-11 07:55:42

浏览器语法Webpack

2013-08-02 10:52:10

Android UI控件

2024-04-07 08:41:34

2024-06-12 00:00:05

2024-08-26 10:01:50

2010-08-25 01:59:00

2011-12-02 09:22:23

网络管理NetQos

2019-07-24 15:30:00

SQL注入数据库

2020-02-21 08:45:45

PythonWeb开发框架

2013-10-16 14:18:02

工具图像处理

2023-04-06 09:08:41

BPM流程引擎

2021-05-20 11:17:49

加密货币区块链印度

2021-10-29 09:32:33

springboot 静态变量项目

2023-09-06 18:37:45

CSS选择器符号

2012-07-25 09:44:31

翼起来·创业咖啡馆

2020-10-19 06:43:53

Redis脚本原子

2023-09-26 00:29:40

CSS布局标签
点赞
收藏

51CTO技术栈公众号