天天看點

分布式服務通訊

在分布式服務架構中,一個最基礎的問題就是遠端服務是怎麼通訊的,在Java領域中有很多可實作遠端通訊的技術,例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什麼關系呢,它們背後到底是基于什麼原理實作的呢,了解這些是實作分布式服務架構的基礎知識,而如果在性能上有高的要求的話,那深入了解這些技術背後的機制就是必須的了,在這篇blog中我們将來一探究竟,抛磚引玉,歡迎大家提供更多的實作遠端通訊的技術和原理的介紹。

基本原理

要實作網絡機器間的通訊,首先得來看看計算機系統網絡通信的基本原理,在底層層面去看,網絡通信需要做的就是将流從一台計算機傳輸到另外一台計算機,基于傳輸協定和網絡IO來實作,其中傳輸協定比較出名的有http、tcp、udp等等,http、tcp、udp都是在為某類應用場景而定義出的傳輸協定,網絡IO,主要有bio、nio、aio三種方式,所有的分布式應用通訊都基于這個原理而實作,隻是為了應用的易用,各種語言通常都會提供一些更為貼近應用易用的應用層協定

應用級協定

遠端服務通訊,需要達到的目标是在一台計算機發起請求,另外一台機器在接收到請求後進行相應的處理并将結果傳回給請求端,這其中又會有諸如one way request、同步請求、異步請求等等請求方式,按照網絡通信原理,需要實作這個需要做的就是将請求轉換成流,通過傳輸協定傳輸至遠端,遠端計算機在接收到請求的流後進行處理,處理完畢後将結果轉化為流,并通過傳輸協定傳回給調用端。

原理是這樣的,但為了應用的友善,業界推出了很多基于此原理之上的應用級的協定,使得大家可以不用去直接操作這麼底層的東西,通常應用級的遠端通信協定會提供:

1、為了避免直接做流操作這麼麻煩,提供一種更加易用或貼合語言的标準傳輸格式;

2、網絡通信機制的實作,就是替你完成了将傳輸格式轉化為流,通過某種傳輸協定傳輸至遠端計算機,遠端計算機在接收到流後轉化為傳輸格式,并進行存儲或以某種方式通知遠端計算機。

是以在學習應用級的遠端通信協定時,我們可以帶着這幾個問題進行學習:

1、傳輸的标準格式是什麼?

2、怎麼樣将請求轉化為傳輸的流?

3、怎麼接收和處理流?

4、傳輸協定是?

不過應用級的遠端通信協定并不會在傳輸協定上做什麼多大的改進,主要是在流操作方面,讓應用層生成流和處理流的這個過程更加的貼合所使用的語言或标準,至于傳輸協定則通常都是可選的,在java領域中知名的有:RMI、XML-RPC、Binary-RPC、SOAP、CORBA、JMS,來具體的看看這些遠端通信的應用級協定:

RMI

RMI是個典型的為java定制的遠端通信協定,我們都知道,在single vm中,我們可以通過直接調用java object instance來實作通信,那麼在遠端通信時,如果也能按照這種方式當然是最好了,這種遠端通信的機制成為RPC(Remote Procedure Call),RMI正是朝着這個目标而誕生的。

來看下基于RMI的一次完整的遠端通信過程的原理:

1、用戶端發起請求,請求轉交至RMI用戶端的stub類;

2、stub類将請求的接口、方法、參數等資訊進行序列化;

3、基于tcp/ip将序列化後的流傳輸至伺服器端;

4、伺服器端接收到流後轉發至相應的skelton類;

5、skelton類将請求的資訊反序列化後調用實際的處理類;

6、處理類處理完畢後将結果傳回給skelton類;

7、Skelton類将結果序列化,通過tcp/ip将流傳送給用戶端的stub;

8、stub在接收到流後反序列化,将反序列化後的Java Object傳回給調用者。

來看jboss-remoting對于此過程的一個更好的圖示:

根據原理來回答下之前學習應用級協定帶着的幾個問題:

1、傳輸的标準格式是什麼?

是Java ObjectStream。

2、怎麼樣将請求轉化為傳輸的流?

基于Java串行化機制将請求的java object資訊轉化為流。

3、怎麼接收和處理流?

根據采用的協定啟動相應的監聽端口,當有流進入後基于Java串行化機制将流進行反序列化,并根據RMI協定擷取到相應的處理對象資訊,進行調用并處理,處理完畢後的結果同樣基于java串行化機制進行傳回。

4、傳輸協定是?

tcp/ip。

XML-RPC

XML-RPC也是一種和RMI類似的遠端調用的協定,它和RMI的不同之處在于它以标準的xml格式來定義請求的資訊(請求的對象、方法、參數等),這樣的好處是什麼呢,就是在跨語言通訊的時候也可以使用。

來看下XML-RPC協定的一次遠端通信過程:

1、用戶端發起請求,按照XML-RPC協定将請求資訊進行填充;

2、填充完畢後将xml轉化為流,通過傳輸協定進行傳輸;

3、接收到在接收到流後轉換為xml,按照XML-RPC協定擷取請求的資訊并進行處理;

4、處理完畢後将結果按照XML-RPC協定寫入xml中并傳回。

圖示以上過程:

同樣來回答問題:

1、傳輸的标準格式是?

标準格式的XML。

2、怎麼樣将請求轉化為傳輸的流?

将XML轉化為流。

3、怎麼接收和處理流?

通過監聽的端口擷取到請求的流,轉化為XML,并根據協定擷取請求的資訊,進行處理并将結果寫入XML中傳回。

4、傳輸協定是?

Http。

Binary-RPC

Binary-RPC看名字就知道和XML-RPC是差不多的了,不同之處僅在于傳輸的标準格式由XML轉為了二進制的格式。

同樣來回答問題:

1、傳輸的标準格式是?

标準格式的二進制檔案。

2、怎麼樣将請求轉化為傳輸的流?

将二進制格式檔案轉化為流。

3、怎麼接收和處理流?

通過監聽的端口擷取到請求的流,轉化為二進制檔案,根據協定擷取請求的資訊,進行處理并将結果寫入XML中傳回。

4、傳輸協定是?

Http。

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中的一次遠端通信的過程:

1、用戶端将請求轉化為符合JMS規定的Message;

2、通過JMS API将Message放入JMS Queue或Topic中;

3、如為JMS Queue,則發送中相應的目标Queue中,如為Topic,則發送給訂閱了此Topic的JMS Queue。

4、處理端則通過輪訓JMS Queue,來擷取消息,接收到消息後根據JMS協定來解析Message并處理。

回答問題:

1、傳輸的标準格式是?

JMS規定的Message。

2、怎麼樣将請求轉化為傳輸的流?

将參數資訊放入Message中即可。

3、怎麼接收和處理流?

輪訓JMS Queue來接收Message,接收到後進行處理,處理完畢後仍然是以Message的方式放入Queue中發送或Multicast。

4、傳輸協定是?

不限。

基于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時,會帶着什麼問題去學習呢?

1、是基于什麼協定實作的?

2、怎麼發起請求?

3、怎麼将請求轉化為符合協定的格式的?

4、使用什麼傳輸協定傳輸?

5、響應端基于什麼機制來接收請求?

6、怎麼将流還原為傳輸格式的?

7、處理完畢後怎麼回應?

JBoss-Remoting

Jboss-remoting是由jboss編寫的一個java領域的遠端通訊架構,基于此架構,可以很簡單的實作基于多種傳輸協定的java對象的RPC。

直接來回答問題:

1、是基于什麼協定實作的?

JBoss-Remoting是個通訊架構,是以它支援多種協定方式的通信,例如tcp/ip+io方式、rmi方式、http+io方式等。

2、怎麼發起請求?

在JBoss-Remoting中,隻需将需要發起的請求參數對象傳入jboss-remoting的InvocationRequest對象即可,也可根據協定基于InvocationRequest封裝符合需求的InvocationRequest對象。

3、怎麼将請求轉化為符合協定的格式的?

JBoss-Remoting基于Java串行化機制或JBoss自己的串行化實作來将請求轉化為對象位元組流。

4、使用什麼傳輸協定傳輸?

支援多種傳輸協定,例如tcp/ip、http等。

5、響應端基于什麼機制來接收請求?

響應端隻需将自己的處理對象注冊到JBoss-Remoting提供的server端的Connector對象中即可。

6、怎麼将流還原為傳輸格式的?

JBoss-Remoting基于java串行化機制或jboss自己的串行化實作來将請求資訊還原為java對象。

7、處理完畢後怎麼回應?

處理完畢後将結果對象直接傳回即可,jboss-remoting會将此對象按照協定進行序列化,傳回至調用端。

另外,jboss-remoting支援多種通信方式,例如同步/異步/單向通信等。

Spring-Remoting

Spring-remoting是Spring提供java領域的遠端通訊架構,基于此架構,同樣也可以很簡單的将普通的spring bean以某種遠端協定的方式來釋出,同樣也可以配置spring bean為遠端調用的bean。

1、是基于什麼協定實作的?

和JBoss-Remoting一樣,作為一個遠端通訊的架構,Spring通過內建多種遠端通訊的library,進而實作了對多種協定的支援,例如rmi、http+io、xml-rpc、binary-rpc等。

2、怎麼發起請求?

在Spring中,由于其對于遠端調用的bean采用的是proxy實作,發起請求完全是通過服務接口調用的方式。

3、怎麼将請求轉化為符合協定的格式的?

Spring按照協定方式将請求的對象資訊轉化為流,例如Spring Http Invoker是基于Spring自己定義的一個協定來實作的,傳輸協定上采用的為http,請求資訊是基于java串行化機制轉化為流進行傳輸。

4、使用什麼傳輸協定傳輸?

支援多種傳輸協定,例如rmi、http等等。

5、響應端基于什麼機制來接收請求?

響應端遵循協定方式來接收請求,對于使用者而言,則隻需通過spring的配置方式将普通的spring bean配置為響應端或者說提供服務端。

6、怎麼将流還原為傳輸格式的?

按照協定方式來進行還原。

7、處理完畢後怎麼回應?

處理完畢後直接傳回即可,spring-remoting将根據協定方式來做相應的序列化。

Hessian

Hessian是由caucho提供的一個基于binary-RPC實作的遠端通訊library。

1、是基于什麼協定實作的?

基于Binary-RPC協定實作。

2、怎麼發起請求?

需通過Hessian本身提供的API來發起請求。

3、怎麼将請求轉化為符合協定的格式的?

Hessian通過其自定義的串行化機制将請求資訊進行序列化,産生二進制流。

4、使用什麼傳輸協定傳輸?

Hessian基于Http協定進行傳輸。

5、響應端基于什麼機制來接收請求?

響應端根據Hessian提供的API來接收請求。

6、怎麼将流還原為傳輸格式的?

Hessian根據其私有的串行化機制來将請求資訊進行反序列化,傳遞給使用者時已是相應的請求資訊對象了。

7、處理完畢後怎麼回應?

處理完畢後直接傳回,hessian将結果對象進行序列化,傳輸至調用端。

Burlap

Burlap也是有caucho提供,它和hessian的不同在于,它是基于XML-RPC協定的。

1、是基于什麼協定實作的?

基于XML-RPC協定實作。

2、怎麼發起請求?

根據Burlap提供的API。

3、怎麼将請求轉化為符合協定的格式的?

将請求資訊轉化為符合協定的XML格式,轉化為流進行傳輸。

4、使用什麼傳輸協定傳輸?

Http協定。

5、響應端基于什麼機制來接收請求?

監聽Http請求。

6、怎麼将流還原為傳輸格式的?

根據XML-RPC協定進行還原。

7、處理完畢後怎麼回應?

傳回結果寫入XML中,由Burlap傳回至調用端。

XFire、Axis

XFire、Axis是Webservice的實作架構,WebService可算是一個完整的SOA架構實作标準了,是以采用XFire、Axis這些也就意味着是采用webservice方式了。

1、是基于什麼協定實作的?

基于SOAP協定。

2、怎麼發起請求?

擷取到遠端service的proxy後直接調用。

3、怎麼将請求轉化為符合協定的格式的?

将請求資訊轉化為遵循SOAP協定的XML格式,由架構轉化為流進行傳輸。

4、使用什麼傳輸協定傳輸?

Http協定。

5、響應端基于什麼機制來接收請求?

監聽Http請求。

6、怎麼将流還原為傳輸格式的?

根據SOAP協定進行還原。

7、處理完畢後怎麼回應?

傳回結果寫入XML中,由架構傳回至調用端。

ActiveMQ

ActiveMQ是JMS的實作,基于JMS這類消息機制實作遠端通訊是一種不錯的選擇,畢竟消息機制本身的功能使得基于它可以很容易的去實作同步/異步/單向調用等,而且消息機制從容錯角度上來說也是個不錯的選擇,這是Erlang能夠做到容錯的重要基礎。

1、是基于什麼協定實作的?

基于JMS協定。

2、怎麼發起請求?

遵循JMS API發起請求。

3、怎麼将請求轉化為符合協定的格式的?

不太清楚,猜想應該是二進制流。

4、使用什麼傳輸協定傳輸?

支援多種傳輸協定,例如tcp/ip、udp、http等等。

5、響應端基于什麼機制來接收請求?

監聽符合協定的端口。

6、怎麼将流還原為傳輸格式的?

同問題3。

7、處理完畢後怎麼回應?

遵循JMS API生成消息,并寫入JMS Queue中。

基于JMS此類機制實作遠端通訊的例子有Spring-Intergration、Mule、Lingo等等。

Mina

Mina是Apache提供的通訊架構,在之前一直沒有提到網絡IO這塊,之前提及的架構或library基本都是基于BIO的,而Mina是采用NIO的,NIO在并發量增長時對比BIO而言會有明顯的性能提升,而java性能的提升,與其NIO這塊與OS的緊密結合是有不小的關系的。

1、是基于什麼協定實作的?

可選的傳輸協定+NIO。

2、怎麼發起請求?

通過Mina提供的Client API。

3、怎麼将請求轉化為符合協定的格式的?

Mina遵循java串行化機制對請求對象進行序列化。

4、使用什麼傳輸協定傳輸?

支援多種傳輸協定,例如tcp/ip、http等等。

5、響應端基于什麼機制來接收請求?

以NIO的方式監聽協定端口。

6、怎麼将流還原為傳輸格式的?

遵循java串行化機制對請求對象進行反序列化。

7、處理完畢後怎麼回應?

遵循Mina API進行傳回。

MINA是NIO方式的,是以支援異步調用是毫無懸念的。

EJB

EJB最突出的在于其分布式,EJB采用的是ORMI協定,和RMI協定是差不多的,但EJB在分布式通訊的安全控制、transport pool、smart proxy等方面的突出使得其在分布式領域是不可忽視的力量。

1、是基于什麼協定實作的?

基于ORMI協定。

2、怎麼發起請求?

EJB調用。

3、怎麼将請求轉化為符合協定的格式的?

遵循java串行化機制對請求對象進行序列化。

4、使用什麼傳輸協定傳輸?

tcp/ip。

5、響應端基于什麼機制來接收請求?

監聽協定端口。

6、怎麼将流還原為傳輸格式的?

遵循java串行化機制對請求對象進行反序列化。

7、處理完畢後怎麼回應?

直接傳回處理對象即可。

在之前的分布式服務架構系列的文章中對于jndi有誤導的嫌疑,在這篇blog中也順帶的提下jndi的機制,由于JNDI取決于具體的實作,在這裡隻能是講解下jboss的jndi的實作了。

在将對象執行個體綁定到jboss jnp server後,當遠端端采用context.lookup()方式擷取遠端對象執行個體并開始調用時,jboss jndi的實作方法是從jnp server上擷取對象執行個體,将其序列化回本地,然後在本地進行反序列化,之後在本地進行類調用。

通過這個機制,就可以知道了,本地其實是必須有綁定到jboss上的對象執行個體的class的,否則反序列化的時候肯定就失敗了,而遠端通訊需要做到的是在遠端執行某動作,并擷取到相應的結果,可見純粹基于JNDI是無法實作遠端通訊的。

但JNDI也是實作分布式服務架構一個很關鍵的技術點,因為可以通過它來實作透明化的遠端和本地調用,就像ejb,另外它也是個很好的隐藏實際部署機制(就像datasource)等的方案。

總結

由上一系列的分析可知,在遠端通訊領域中,涉及的知識點還是相當的多的,例如有:通信協定或遠端調用協定(tcp/http/udp/rmi/xml-rpc etc.)、消息機制、網絡IO(BIO/NIO/AIO)、MultiThread、本地調用與遠端調用的透明化方案(涉及java classloader、Dynamic Proxy、Unit Test etc.)、異步與同步調用、網絡通信處理機制(自動重連、廣播、異常、池處理等等)、Java Serialization (各種協定的私有序列化機制等)、各種架構的實作原理(傳輸格式、如何将傳輸格式轉化為流的、如何将請求資訊轉化為傳輸格式的、如何接收流的、如何将流還原為傳輸格式的等等),要精通其中的哪些東西,得根據實際需求來決定了,隻有在了解了原理的情況下才能很容易的做出選擇,甚至可以根據需求做私有的遠端通訊協定,對于從事分布式服務平台或開發較大型的分布式應用的人而言,我覺得至少上面提及的知識點是需要比較了解的。

參考文檔(感謝這些文章)

RMI原理及實作:http://www.yesky.com/274/1625274.shtml

Java NIO原理和使用:http://www.jdon.com/concurrent/nio%D4%AD%C0%ED%D3%A6%D3%C3.htm

XML RPC協定:http://hedong.3322.org/archives/000470.html

http://www.mengyan.org/blog/archives/2005/07/12/30.html

Spring技術應用中的遠端服務詳解:http://www.builder.com.cn/2007/1027/583384.shtml

JAVA RPC通信機制之SOAP:http://www.java114.com/content16/content3826.html

Java Remoting:Protocol BenchMarks:http://q.sohu.com/forum/5/topic/1148909

Evalution of RMI Alternative:https://www.jfire.org/modules/phpwiki/index.php/Evaluation%20of%20RMI%20Alternative

Metaprotocol Taxonomy:http://hessian.caucho.com/doc/metaprotocol-taxonomy.xtp

什麼是Webservice:http://www.vchome.net/dotnet/webservice/webservice15.htm

轉載:http://www.uml.org.cn/zjjs/201208011.asp

繼續閱讀