`
ahuaxuan
  • 浏览: 633853 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

RPC or noRPC,这是个问题

阅读更多

/**

   * author:ahuaxuan

   * date:2010-04-21

   */

修改,避免引起混淆,特别说明本文中的非RPC方式其本质也是RPC,只是非RPC由服务器端定义好序列化规则和协议,然后让调用者自己去实现,而本文中的RPC指服务提供者提供Jar,客户端可以直接调用接口.不需要考虑到网络,协议,序列化算法.

 

很多公司都会遇到应用集成的一些问题,其中一项就是RPC的问题.


企业内部应用集成(请求应答模式)的通信一般有方式,一种是RPC方式,另外一个是非RPC方式.
先说说非RPC方式的实现:比如说A-Y这25个应用依赖于Z这个应用,那么Z应用将丢一个开发文档给A-Y个应用的开发人员,告诉他们说,
照着文档开发吧,A-Y个应用的开发人员打开文档,看到一个URL, 然后就是URL中需要的参数.

于是A-Y个应用开始开发各自和Z应用通信的程序.

RPC方式实现:
Z应用直接提供一个jar包给A-Y个应用,然后A-Y应用导入这个jar,然后直接调用接口.具体的实现可以参考hessian RPC.

使用RPC的好处是你不需要考虑对象这么序列化成bytes传到server,也不需要考虑从server过来的bytes这么反序列化成接口的返回值.

这些内部的实现A-Y的开发者完全不需要考虑.


很多人偏向RPC方式,也有人偏向非PRC方式.那么ahuaxuan先来阐述一下他们的优缺点:

非RPC方式:
优点:
1.A-Y的代码功能相同,但是实现方式不一样,一个出现bug,不会影响其他24个应用.其他24个应用不需要重启以导入新的jar包
2.A-Y的代码不需要引入Z应用的J <script src="/javascripts/tinymce/themes/advanced/langs/zh.js" type="text/javascript"></script><script src="/javascripts/tinymce/plugins/javaeye/langs/zh.js" type="text/javascript"></script> ar包.
3.Z应用的开发者由于不需要提供client的jar包,所以不需要承担bug带来的责任.

缺点:
1.A-Y的开发者重复造轮子,25次.
2.A-Y的测试者重复测试.
3.如果一个client的实现+单元测试+ 集成测试和调试需要4 manday,那么24次多余的劳动会带来96个manday的浪费
4.重复的测试达到24次,每次是2个manday,那么又48个manday的浪费,总共的浪费高达96+48=144manday.
5.每次Z的修改都可能造成这样的浪费.

6.文档中要定义接口的错误状态码.然后客户端需要关心这些状态码的实现.


再说说RPC方式:
优点:
1.A-Y个应用不需要开发这个功能,直接引入jar包,调用接口,2分钟完成这部分工作.
2.Z应用对外的接口在Z的新版本开发时不修改老接口,只增加新接口.达到一定的兼容性.

3.不需要考虑对象这么序列化成bytes传到server,也不需要考虑从server过来的bytes这么反序列化成接口的返回值.

这些内部的实现A-Y的开发者完全不需要考虑.

4.不需要考虑序列化完成之后的bytes怎么传输,是http,还是直接基于TCP, 是nio还是bio等等

5.异常可以直接序列化到客户端,客户端调用者不需要去研究什么状态码,只要看一下异常的种类就行了.

6.客户端可以直接验证输入参数的合法性,无需到服务器上验证, 提供接口的人更清楚他们接受什么样的参数




缺点:
1.Z应用的开发者需要承担责任,如果client的Jar在线上出现bug,他们难辞其咎.(但这对A-Y的开发者来说是个优点)
2.如果jar包线上出bug,那么A-Y个应用都需要重启,并引入新的jar包.
3.不能满足一些人自以为是的欲望,因为有一些人一直觉得自己的代码是最好的,所以他们宁可重复造轮子.




接下来请各位同学做一道选择题:

请站在非A-Z应用的开发者角度(请站在对整个架构有利的角度)来选择这些企业内部应用集成的方式:

 


A. RPC方式
B. 非RPC方式

如果你有除了我上面列出的其他优缺点,可以在你选择的答案后面列出来.


虽然这不是一个纯技术贴,但是我想大家在发展的过程中都或多或少会遇到这样的问题(这个问题是:很多时候你坚信是正确的事情但是却得不到上面的执行和认可,所以我们只有两个选择,1.曲线救国,2.放下不管,).希望大家支持,踊跃参与.

分享到:
评论
40 楼 ahuaxuan 2010-04-01  
linkerlin 写道
个人非常推荐PHPRPC.
这个不是PHP的RPC,
而是跨语言的RPC

我能理解你的心情,但是我也希望你不要答非所问.

yanwt 写道
hatedance 写道
举个实际的例子,alipay,
它实际上是restful的接口。但同时也提供了java和其他语言的wrapper,大多数人会用。

同意这个观点,虽然我们现在内部使用的是hessian,但是我觉得对于一个对外部提供服务的业务来说,不应该限制客户端的语言,可以提供默认的实现。有客户自己决定用与不用。

现在很多rpc都没有语言限制阿,只要你的序列化方式是同用的,那么基本上就没有语言限制.比如说:
hessian
thirft
protobuffer
PHPRPC

等等.

alipay的场景和我们还有区别,alipay是个独立的平台,hatedance描述的是独立平台之间的依赖.
我们的场景包括平台内部和平台之间这两种.如果是平台内部应用的调用,搞那么多只是增加了成本降低可维护性.
39 楼 yanwt 2010-04-01  
hatedance 写道
举个实际的例子,alipay,
它实际上是restful的接口。但同时也提供了java和其他语言的wrapper,大多数人会用。

同意这个观点,虽然我们现在内部使用的是hessian,但是我觉得对于一个对外部提供服务的业务来说,不应该限制客户端的语言,可以提供默认的实现。有客户自己决定用与不用。
38 楼 ahuaxuan 2010-04-01  
JE帐号 写道
sorphi 写道
感觉本贴说明的是这两个抉择:
A、需要服务端提供支持库(包括数据结构、客户端)
B、只需要服务提供调用协议。

协议也是一种接口,其中也包括了数据结构描述。从这个角度来说,服务端提供的支持库实际上是协议的一种具体实现了。

客户端采用支持库,方便、性能好些,但是被耦合了。

企业内部,容易沟通,舍弃一个可统一协调维护的支持库不用,非得绕弯来各自实现协议,有点隔靴挠痒的感觉。看似解耦了,实际成本却高。



就我个人实践的经验看,和你说的恰恰相反.
多个项目都去依赖一个库,只要这个项目群有一定的活跃度,一定会周期性的出现大的重构需求.至于重构对各依赖项目群的影响能有多少,及其考验支持库的设计者(语言技巧和业务理解).这还是说的项目群的进度在业务上一致的情况,如果出现系统本身升级,但是项目群又无法同步的切换,依赖包给做大量的兼容甚至给出多个版本.成本一点一不低.


这样的场景我们是否可以通过项目管理来实现控制.

1.在依赖库升级的时候保证对修改封闭,对扩展开放的原则,这样不会出现修改已有接口的情况发生.
2.只兼容有限的最近几个接口,也就是说老版本支持只保持在一定的版本号之内.

我们公司能做到这一点并不难,原因有2个:

1.企业内部使用的依赖库做到这一点并不难,但是如果是对公众开放的依赖库这样做就不合适了.

2.我之所以说我们做到这一点并不难还有一个原因,就是我们也是属于互联网产品的一部分,互联网产品更新的速度是非常高的,大多数情况下Z的客户端升级的时候,A-Y也存在升级的需求了.
37 楼 ahuaxuan 2010-04-01  
sorphi 写道
感觉本贴说明的是这两个抉择:
A、需要服务端提供支持库(包括数据结构、客户端)
B、只需要服务提供调用协议。

协议也是一种接口,其中也包括了数据结构描述。从这个角度来说,服务端提供的支持库实际上是协议的一种具体实现了。

客户端采用支持库,方便、性能好些,但是被耦合了。

企业内部,容易沟通,舍弃一个可统一协调维护的支持库不用,非得绕弯来各自实现协议,有点隔靴挠痒的感觉。看似解耦了,实际成本却高。


说实话,非常同意你的观点.

各自实现只是看似解耦,因为发生需求变动的时候,A-Y个应用的开发者是非常痛苦的,他们要阅读文档中变化的地方,而且会提出各种问题,接着Z的开发者就不停的解答这些问题,沟通的成本非常高,从这个角度来看,项目之间的耦合程度是非常高的.
36 楼 mathgl 2010-04-01  
这个是看情况的吧。。如果是新系统
我倾向用rpc。现在我就用ice。phprpc也用过。

旧系统 如果不好做rpc。就用非rpc 封装一层。
35 楼 hatedance 2010-04-01  
举个实际的例子,alipay,
它实际上是restful的接口。但同时也提供了java和其他语言的wrapper,大多数人会用。
34 楼 zoutm 2010-04-01  
JE帐号 写道
sorphi 写道
感觉本贴说明的是这两个抉择:
A、需要服务端提供支持库(包括数据结构、客户端)
B、只需要服务提供调用协议。

协议也是一种接口,其中也包括了数据结构描述。从这个角度来说,服务端提供的支持库实际上是协议的一种具体实现了。

客户端采用支持库,方便、性能好些,但是被耦合了。

企业内部,容易沟通,舍弃一个可统一协调维护的支持库不用,非得绕弯来各自实现协议,有点隔靴挠痒的感觉。看似解耦了,实际成本却高。



就我个人实践的经验看,和你说的恰恰相反.
多个项目都去依赖一个库,只要这个项目群有一定的活跃度,一定会周期性的出现大的重构需求.至于重构对各依赖项目群的影响能有多少,及其考验支持库的设计者(语言技巧和业务理解).这还是说的项目群的进度在业务上一致的情况,如果出现系统本身升级,但是项目群又无法同步的切换,依赖包给做大量的兼容甚至给出多个版本.成本一点一不低.


比较赞同robbin的观点,如果是企业内部的整合集成,采用RPC相对好些,性能高,规模也容易控制,而且RPC可以提供比restFul更多的特性,第三方集成采用restFul更合适,第三方总想有更多的控制,而且restful接口一目了然,也比较容易进行问题分析。
33 楼 JE帐号 2010-04-01  
sorphi 写道
感觉本贴说明的是这两个抉择:
A、需要服务端提供支持库(包括数据结构、客户端)
B、只需要服务提供调用协议。

协议也是一种接口,其中也包括了数据结构描述。从这个角度来说,服务端提供的支持库实际上是协议的一种具体实现了。

客户端采用支持库,方便、性能好些,但是被耦合了。

企业内部,容易沟通,舍弃一个可统一协调维护的支持库不用,非得绕弯来各自实现协议,有点隔靴挠痒的感觉。看似解耦了,实际成本却高。



就我个人实践的经验看,和你说的恰恰相反.
多个项目都去依赖一个库,只要这个项目群有一定的活跃度,一定会周期性的出现大的重构需求.至于重构对各依赖项目群的影响能有多少,及其考验支持库的设计者(语言技巧和业务理解).这还是说的项目群的进度在业务上一致的情况,如果出现系统本身升级,但是项目群又无法同步的切换,依赖包给做大量的兼容甚至给出多个版本.成本一点一不低.

32 楼 sorphi 2010-04-01  
感觉本贴说明的是这两个抉择:
A、需要服务端提供支持库(包括数据结构、客户端)
B、只需要服务提供调用协议。

协议也是一种接口,其中也包括了数据结构描述。从这个角度来说,服务端提供的支持库实际上是协议的一种具体实现了。

客户端采用支持库,方便、性能好些,但是被耦合了。

企业内部,容易沟通,舍弃一个可统一协调维护的支持库不用,非得绕弯来各自实现协议,有点隔靴挠痒的感觉。看似解耦了,实际成本却高。

31 楼 linkerlin 2010-04-01  
个人非常推荐PHPRPC.
这个不是PHP的RPC,
而是跨语言的RPC
30 楼 JE帐号 2010-04-01  
assiwe 写道
推荐用REST方式。 你们的系统不可能一直不变,以后有可能扩展,也有可能和其他公司结合.用PRC跨语言费劲,尤其是你们这边是java写的

LZ说的区别:1.A-Y的代码功能相同,既然相同就不应该有这么多的重复应用。如果是在说解析数据的代码的话,这个代码实际上很少。
2.扩展时Z代码如果可以不修改老接口,那么用REST也一样可以,甚至更方便。
3.4.这两个是Z-提供者考虑的事情。

我猜测LZ实际上没做过NoPRC,所以才希望选择PRC的方式

PRC和REST比较
REST方式耦合度更低,扩展方便,跨语言。
PRC性能较好(但实际上意义不大,因为一般来说通信都不是性能瓶颈)。
如果Z应用和A-Y应用是同一小组开发的话,可以用PRC。否则还是REST的好。


就我所了解的,你这里说的REST其实就是soap或者其变种(载体为json)其实本质上还是是RPC.
REST所代表的是对架构的影响,是一种分解问题的新思路.而不只是体现在接口形式的简单和语言无关性上.
29 楼 assiwe 2010-04-01  
推荐用REST方式。 你们的系统不可能一直不变,以后有可能扩展,也有可能和其他公司结合.用PRC跨语言费劲,尤其是你们这边是java写的

LZ说的区别:1.A-Y的代码功能相同,既然相同就不应该有这么多的重复应用。如果是在说解析数据的代码的话,这个代码实际上很少。
2.扩展时Z代码如果可以不修改老接口,那么用REST也一样可以,甚至更方便。
3.4.这两个是Z-提供者考虑的事情。

我猜测LZ实际上没做过NoPRC,所以才希望选择PRC的方式

PRC和REST比较
REST方式耦合度更低,扩展方便,跨语言。
PRC性能较好(但实际上意义不大,因为一般来说通信都不是性能瓶颈)。
如果Z应用和A-Y应用是同一小组开发的话,可以用PRC。否则还是REST的好。
28 楼 rainlife 2010-04-01  
无废话,偏向于RPC。
当然,为了不显示我偷懒,加一句“根据实际情况选择”。
27 楼 JE帐号 2010-04-01  
没实际应用过REST就不谈REST了.

而你说的那种RPC,我也不是很赞同,我还是更推崇接口传递简单格式化对象.如json或xml.在涉及到要和别人的系统联动时,这种语言无关的特性经常会让你感动的内牛满面.自然bean2xml/json或xml/json2bean的工作很繁琐,但是都可以通过工具减负.当然了,性能差了些.
26 楼 Dreamer 2010-04-01  
靠,我被外星人劫持了整整20天
25 楼 andot 2010-04-01  
我也同意使用RPC方式,这种方式实际上可以更好的降低系统耦合性,业务模块在不需要重新编写的情况下,就可以替换成不同的RPC方式发布,而如果用非RPC传参方式,就没有这么方便了。而且的RPC包对跨平台跨语言支持的也很好,比如PHPRPC、Hprose等,所以完全可以提到原始的低效的非RPC方式。
24 楼 xujunJ2EE 2010-04-01  
我觉得还是看应用的具体需求,比如在同构系统中,并且是非工业级的系统中,RPC应该是首选。
在异构系统中,对实时性要求高的,不能使用HTTP协议的,应该用noRPC。比如我们作电力系统实时监控中,通讯协议都是有标准的,只能自己作TCP/IP通讯
23 楼 ahuaxuan 2010-04-01  
rocwon 写道
这个问题...个人觉得已经不是啥问题。
比如你要提供一个服务S给应用A使用,那么其实你的服务S可以包装成S-RPC,S-REST,S-WS。。。。

这个问题不是使用什么RPC,而是是否使用RPC,但是你的回答也表明了你的观点.
22 楼 rocwon 2010-04-01  
这个问题...个人觉得已经不是啥问题。
比如你要提供一个服务S给应用A使用,那么其实你的服务S可以包装成S-RPC,S-REST,S-WS。。。。
21 楼 ahuaxuan 2010-04-01  
hatedance 写道
我看问题本质没区别。
假设底层通讯机制是http,那么你再提供一个默认的jar包用以封装http接口为更高级的java接口,人家爱用不用。出了任何bug当然要维护。
当然,人家想发明轮子也未尝不可,因为你提供的只是一种缺省实现而已。
这个jar包如果很简单,那么也无所谓重复不重复。
如果很复杂,那么谁也不愿意自己做轮子,毕竟需要成本。
所以总之还是你提供一个jar包比较好。

功能上来讲本质上有确实也没有什么区别的呀,举例Mina和netty或者自己写nio本质上也没有什么区别.只是实现方式不一样.我在前面的帖子中也说明了我的观点,我们有时候不是只需要考虑功能是否能实现就可以了,实现功能只是基本要求


linkerlin 写道
推荐PHPRPC

文章的题目不是用哪个RPC,而是是否用RPC,但是你的回答也表明了你的观点.

相关推荐

Global site tag (gtag.js) - Google Analytics