在分布式服务框架中,一个最基础的问题就是远程服务是怎么通讯的,在java领域中有很多可实现远程通讯的技术,例如:rmi、mina、esb、burlap、hessian、soap、ejb和jms 等,这些名词之间到底是些什么关系呢,它们背后到底是基于什么原理实现的呢,了解这些是实现分布式服务框架的基础知识,而如果在性能上有高的要求的话,那深入了解这些技术背后的机制就是必须的了,在这篇blog中我们将来一探究竟,抛砖引玉,欢迎大家提供更多的实现远程通讯的技术和原理的介绍。
基本原理
要实现网络机器间的通讯,首先得来看看计算机系统网络通信的基本原理,在底层层面去看,网络通信需要做的就是将流从一台计算机传输到另外一台计算机,基于传输协议和网络io来实现,其中传输协议比较出名的有http、tcp、udp等等,http、tcp、udp都是在基于socket概念上为某类应用场景而扩展出的传输协议,网络io,主要有bio、nio、aio三种方式,所有的分布式应用通讯都基于这个原理而实现,只是为了应用的易用,各种语言通常都会提供一些更为贴近应用易用的应用层协议。
应用级协议
远程服务通讯,需要达到的目标是在一台计算机发起请求,另外一台机器在接收到请求后进行相应的处理并将结果返回给请求端,这其中又会有诸如one way request、同步请求、异步请求等等请求方式,按照网络通信原理,需要实现这个需要做的就是将请求转换成流,通过传输协议传输至远端,远端计算机在接收到请求的流后进行处理,处理完毕后将结果转化为流,并通过传输协议返回给调用端。
原理是这样的,但为了应用的方便,业界推出了很多基于此原理之上的应用级的协议,使得大家可以不用去直接操作这么底层的东西,通常应用级的远程通信协议会提供:
所以在学习应用级的远程通信协议时,我们可以带着这几个问题进行学习:
不过应用级的远程通信协议并不会在传输协议上做什么多大的改进,主要是在流操作方面,让应用层生成流和处理流的这个过程更加的贴合所使用的语言或标准,至于传输协议则通常都是可选的,在java领域中知名的有:rmi、xml-rpc、binary-rpc、soap、corba、jms,来具体的看看这些远程通信的应用级协议:
rmi
rmi是个典型的为java定制的远程通信协议,我们都知道,在single vm中,我们可以通过直接调用java object instance来实现通信,那么在远程通信时,如果也能按照这种方式当然是最好了,这种远程通信的机制成为rpc(remote procedure call),rmi正是朝着这个目标而诞生的。
来看下基于rmi的一次完整的远程通信过程的原理:
根据原理来回答下之前学习应用级协议带着的几个问题:
xml-rpc
xml-rpc也是一种和rmi类似的远程调用的协议,它和rmi的不同之处在于它以标准的xml格式来定义请求的信息(请求的对象、方法、参数等),这样的好处是什么呢,就是在跨语言通讯的时候也可以使用。
来看下xml-rpc协议的一次远程通信过程:
同样来回答问题:
binary-rpc
binary-rpc看名字就知道和xml-rpc是差不多的了,不同之处仅在于传输的标准格式由xml转为了二进制的格式。
同样来回答问题:
soap
soap原意为simple object access protocol,是一个用于分布式环境的、轻量级的、基于xml进行信息交换的通信协议,可以认为soap是xml rpc的高级版,两者的原理完全相同,都是http+xml,不同的仅在于两者定义的xml规范不同,soap也是webservice采用的服务调用协议标准,因此在此就不多加阐述了。
corba
common object request broker architecture(公用对象请求代理[调度]程序体系结构),是一组用来定义“分布式对象系统”的标准,由omg(object menagement group)作为发起和标准制定单位。corba的目的是定义一套协议,符合这个协议的对象可以互相交互,不论它们是用什么样的语言写的,不论它们运行于什么样的机器和操作系统。
corba在我看来是个类似于soa的体系架构,涵盖可选的远程通信协议,但其本身不能列入通信协议这里来讲,而且corba基本淘汰,再加上对corba也不怎么懂,在此就不进行阐述了。
jms
jms呢,是实现java领域远程通信的一种手段和方法,基于jms实现远程通信时和rpc是不同的,虽然可以做到rpc的效果,但因为不是从协议级别定义的,因此我们不认为jms是个rpc协议,但它确实是个远程通信协议,在其他的语言体系中也存在着类似jms的东西,可以统一的将这类机制称为消息机制,而消息机制呢,通常是高并发、分布式领域推荐的一种通信机制,这里的主要一个问题是容错(详细见erlang论文)。
来看jms中的一次远程通信的过程:
回答问题:
基于jms也是常用的实现远程异步调用的方法之一。
可选实现技术
当然,在上面的原理中并没有介绍到所有的java领域可选的远程通信协议了,例如还有ejb采用的ormi、spring自己定义的一个简单的http invoker等等。
看完原理后我们再来看看目前java领域可用于实现远程通讯的框架或library,知名的有:jboss-remoting、spring- remoting、hessian、burlap、xfire(axis)、activemq、mina、mule、ejb3等等,来对每种做个简单的介绍和评价,其实呢,要做分布式服务框架,这些东西都是要有非常深刻的了解的,因为分布式服务框架其实是包含了解决分布式领域以及应用层面领域两方面问题的。
当然,你也可以自己根据远程网络通信原理(transport protocol+net io)去实现自己的通讯框架或library。
那么在了解这些远程通讯的框架或library时,会带着什么问题去学习呢?
jboss-remoting
jboss-remoting是由jboss编写的一个java领域的远程通讯框架,基于此框架,可以很简单的实现基于多种传输协议的java对象的rpc。
直接来回答问题:
另外,jboss-remoting支持多种通信方式,例如同步/异步/单向通信等。
spring-remoting
spring-remoting是spring提供java领域的远程通讯框架,基于此框架,同样也可以很简单的将普通的spring bean以某种远程协议的方式来发布,同样也可以配置spring bean为远程调用的bean。
hessian
hessian是由caucho提供的一个基于binary-rpc实现的远程通讯library。
burlap
burlap也是有caucho提供,它和hessian的不同在于,它是基于xml-rpc协议的。
xfire、axis
xfire、axis是webservice的实现框架,webservice可算是一个完整的soa架构实现标准了,因此采用xfire、axis这些也就意味着是采用webservice方式了。
activemq
activemq是jms的实现,基于jms这类消息机制实现远程通讯是一种不错的选择,毕竟消息机制本身的功能使得基于它可以很容易的去实现同步/异步/单向调用等,而且消息机制从容错角度上来说也是个不错的选择,这是erlang能够做到容错的重要基础。
基于jms此类机制实现远程通讯的例子有spring-intergration、mule、lingo等等。
mina
mina是apache提供的通讯框架,在之前一直没有提到网络io这块,之前提及的框架或library基本都是基于bio的,而mina是采用 nio的,nio在并发量增长时对比bio而言会有明显的性能提升,而java性能的提升,与其nio这块与os的紧密结合是有不小的关系的。
mina是nio方式的,因此支持异步调用是毫无悬念的。
ejb
ejb最突出的在于其分布式,ejb采用的是ormi协议,和rmi协议是差不多的,但ejb在分布式通讯的安全控制、transport pool、smart proxy等方面的突出使得其在分布式领域是不可忽视的力量。
在之前的分布式服务框架系列的文章中对于jndi有误导的嫌疑,在这篇blog中也顺带的提下jndi的机制,由于jndi取决于具体的实现,在这里只能是讲解下jboss的jndi的实现了。
在将对象实例绑定到jboss jnp server后,当远程端采用context.lookup()方式获取远程对象实例并开始调用时,jboss jndi的实现方法是从jnp server上获取对象实例,将其序列化回本地,然后在本地进行反序列化,之后在本地进行类调用。
通过这个机制,就可以知道了,本地其实是必须有绑定到jboss上的对象实例的class的,否则反序列化的时候肯定就失败了,而远程通讯需要做到的是在远程执行某动作,并获取到相应的结果,可见纯粹基于jndi是无法实现远程通讯的。
但jndi也是实现分布式服务框架一个很关键的技术点,因为可以通过它来实现透明化的远端和本地调用,就像ejb,另外它也是个很好的隐藏实际部署机制(就像datasource)等的方案。
总结
由上一系列的分析可知,在远程通讯领域中,涉及的知识点还是相当的多的,例如有:通信协议(socket/tcp/http/udp/rmi /xml-rpc etc.)、消息机制、网络io(bio/nio/aio)、multithread、本地调用与远程调用的透明化方案(涉及java classloader、dynamic proxy、unit test etc.)、异步与同步调用、网络通信处理机制(自动重连、广播、异常、池处理等等)、java serialization (各种协议的私有序列化机制等)、各种框架的实现原理(传输格式、如何将传输格式转化为流的、如何将请求信息转化为传输格式的、如何接收流的、如何将流还原为传输格式的等等),要精通其中的哪些东西,得根据实际需求来决定了,只有在了解了原理的情况下才能很容易的做出选择,甚至可以根据需求做私有的远程通讯协议,对于从事分布式服务平台或开发较大型的分布式应用的人而言,我觉得至少上面提及的知识点是需要比较了解的。
参考文档(感谢这些文章)