函数的跨语言/跨内存调用
在我Blog的另一个文章里简单介绍了WebService的原理,以及其最重要的特性,可以跨语言调用API.在文章的末尾也提到了两点:
- WebService效率不高
- WebService还可以不同实体机上跨内存的函数调用
其效率不高的原因就是因为WebServices是基于文本的,而且XML文本的复杂度又很高,解析起来比较慢.
而在企业级别中,多数情况是因为业务过于复杂,会让不同的服务器承担不同的功能,这些功能之间进行互相调用,而服务器上运行的代码往往是同一种语言.所以内部同语言下的跨内存调用需求远大于外部跨语言调用.
如何提高跨内存调用效率
由于WebService效率不高的原因是基于文本,那么我们需要一种更加底层的方法来提高效率,就是RPC(Remote Procedure Call Protocol)框架,关于RPC框架的介绍知乎上回答的很好,我们根据#巴多崽#用心阁#肖继潮#等人的回答一步一步来分析
产生跨区域调用的原因
早期单机时代,一台电脑上运行多个进程,大家各干各的,老死不相往来。假如A进程需要一个画图的功能,B进程也需要一个画图的功能,程序员就必须为两个进程都写一个画图的功能。
这不是整人么?于是就出现了IPC(Inter-process communication,单机中运行的进程之间的相互通信)。OK,现在A既然有了画图的功能,B就调用A进程上的画图功能好了,程序员终于可以偷下懒了。
到了网络时代,大家的电脑都连起来了。以前程序只能调用自己电脑上的进程,能不能调用其他机器上的进程呢?于是就程序员就把IPC扩展到网络上,这就是RPC(远程过程调用)了。现在不仅单机上的进程可以相互通信,多机器中的进程也可以相互通信了。
要知道实现RPC很麻烦呀,什么多线程、什么Socket、什么I/O,都是让咱们普通程序员很头疼的事情。于是就有牛人开发出RPC框架。
RPC框架和WebService的关系
RPC框架不仅局限于一种,最初由Sun公司提出采用客户机/服务器模式,请求程序就是一个客户机,而服务提供程序就是一个服务器.所以说WebService应该属于RPC框架的一种,但是由于目前跨内存调用的普遍性,RPC往往代称更加具体的基于底层协议二进制流的RPC框架,与WebService最大的不同就是
- 狭义的RPC基于二进制流的序列化和反序列化,故不能够提供跨语言的服务,但是比基于文本解析的WebService更加高效
狭义的RPC的工作过程
先假设两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据.
- 首先A和B建立TCP链接,并且确定好RPC框架的网路端口,能够进行网络通信
- 然后A服务器将需要调用B服务器的方法和参数进行序列化(Serialize)或编组(marshal)
- 通过第一步建立的链接,将序列化后的二进制流发送给B
- B服务器收到请求后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式
- 然后B服务器找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值
- B服务器对返回值再次进行序列化,并且通过相同的途径发送给A
- A对B服务器返回的信息再进行反序列化,得到返回结果
整个流程如下图所示
Netty是什么
提到RPC框架会伴随着一个词语Netty,而Netty框架并不局限于RPC,更多的是作为一种网络协议的实现框架.由于RPC需要高效的网络通信,就可能选择以Netty作为基础,Netty十一个答疑看这里.
除了网络通信,RPC还需要有比较高效的序列化框架,以及一种寻址方式.如果是带会话(状态)的RPC调用,还需要有会话和状态保持的功能。
当然最主要的原因还是Netty有许多好处,比如对非阻塞IO(NIO)的支持,比如在链上传递时最大程度的减少buffer的copy(高性能).
Dubbo是什么
Dubbo是阿里公司开发的分布式服务RPC框架,本身使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信。通常与Zookeeper配合使用,整个项目是由阿里的六个开发人员参与开发和测试,并且在Github上进行了开源.Dubbo队员专访看这里.