當然,在上面的原理中並沒有介紹到所有的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是個通訊框架,因此它支持多種協議方式的通信,例如純粹的socket+io方式、rmi方式、http+io方式等。
怎麼發起請求?
在JBoss-Remoting中,只需將需要發起的請求參數對象傳入jboss-remoting的InvocationRequest對象即可,也可根據協議基於InvocationRequest封裝符合需求的InvocationRequest對象。
怎麼將請求轉化爲符合協議的格式的?
JBoss-Remoting基於Java串行化機制或JBoss自己的串行化實現來將請求轉化爲對象字節流。
使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如socket、http等。
響應端基於什麼機制來接收請求?
響應端只需將自己的處理對象註冊到JBoss-Remoting提供的server端的Connector對象中即可。
怎麼將流還原爲傳輸格式的?
JBoss-Remoting基於java串行化機制或jboss自己的串行化實現來將請求信息還原爲java對象。
處理完畢後怎麼迴應?
處理完畢後將結果對象直接返回即可,jboss-remoting會將此對象按照協議進行序列化,返回至調用端。
另外,jboss-remoting支持多種通信方式,例如同步/異步/單向通信等。
Spring-Remoting
Spring-remoting是Spring提供java領域的遠程通訊框架,基於此框架,同樣也可以很簡單的將普通的spring bean以某種遠程協議的方式來發布,同樣也可以配置spring bean爲遠程調用的bean。
是基於什麼協議實現的?
和JBoss-Remoting一樣,作爲一個遠程通訊的框架,Spring通過集成多種遠程通訊的library,從而實現了對多種協議的支持,例如rmi、http+io、xml-rpc、binary-rpc等。
怎麼發起請求?
在Spring中,由於其對於遠程調用的bean採用的是proxy實現,發起請求完全是通過服務接口調用的方式。
怎麼將請求轉化爲符合協議的格式的?
Spring按照協議方式將請求的對象信息轉化爲流,例如Spring Http Invoker是基於Spring自己定義的一個協議來實現的,傳輸協議上採用的爲http,請求信息是基於java串行化機制轉化爲流進行傳輸。
使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如rmi、http等等。
響應端基於什麼機制來接收請求?
響應端遵循協議方式來接收請求,對於使用者而言,則只需通過spring的配置方式將普通的spring bean配置爲響應端或者說提供服務端。
怎麼將流還原爲傳輸格式的?
按照協議方式來進行還原。
處理完畢後怎麼迴應?
處理完畢後直接返回即可,spring-remoting將根據協議方式來做相應的序列化。
Hessian
Hessian是由caucho提供的一個基於binary-RPC實現的遠程通訊library。
是基於什麼協議實現的?
基於Binary-RPC協議實現。
怎麼發起請求?
需通過Hessian本身提供的API來發起請求。
怎麼將請求轉化爲符合協議的格式的?
Hessian通過其自定義的串行化機制將請求信息進行序列化,產生二進制流。
使用什麼傳輸協議傳輸?
Hessian基於Http協議進行傳輸。
響應端基於什麼機制來接收請求?
響應端根據Hessian提供的API來接收請求。
怎麼將流還原爲傳輸格式的?
Hessian根據其私有的串行化機制來將請求信息進行反序列化,傳遞給使用者時已是相應的請求信息對象了。
處理完畢後怎麼迴應?
處理完畢後直接返回,hessian將結果對象進行序列化,傳輸至調用端。
Burlap
Burlap也是有caucho提供,它和hessian的不同在於,它是基於XML-RPC協議的。
是基於什麼協議實現的?
基於XML-RPC協議實現。
怎麼發起請求?
根據Burlap提供的API。
怎麼將請求轉化爲符合協議的格式的?
將請求信息轉化爲符合協議的XML格式,轉化爲流進行傳輸。
使用什麼傳輸協議傳輸?
Http協議。
響應端基於什麼機制來接收請求?
監聽Http請求。
怎麼將流還原爲傳輸格式的?
根據XML-RPC協議進行還原。
處理完畢後怎麼迴應?
返回結果寫入XML中,由Burlap返回至調用端。
XFire、Axis
XFire、Axis是Webservice的實現框架,WebService可算是一個完整的SOA架構實現標準了,因此採用XFire、Axis這些也就意味着是採用webservice方式了。
是基於什麼協議實現的?
基於SOAP協議。
怎麼發起請求?
獲取到遠端service的proxy後直接調用。
怎麼將請求轉化爲符合協議的格式的?
將請求信息轉化爲遵循SOAP協議的XML格式,由框架轉化爲流進行傳輸。
使用什麼傳輸協議傳輸?
Http協議。
響應端基於什麼機制來接收請求?
監聽Http請求。
怎麼將流還原爲傳輸格式的?
根據SOAP協議進行還原。
處理完畢後怎麼迴應?
返回結果寫入XML中,由框架返回至調用端。
ActiveMQ
ActiveMQ是JMS的實現,基於JMS這類消息機制實現遠程通訊是一種不錯的選擇,畢竟消息機制本身的功能使得基於它可以很容易的去實現同步/異步/單向調用等,而且消息機制從容錯角度上來說也是個不錯的選擇,這是Erlang能夠做到容錯的重要基礎。
是基於什麼協議實現的?
基於JMS協議。
怎麼發起請求?
遵循JMS API發起請求。
怎麼將請求轉化爲符合協議的格式的?
不太清楚,猜想應該是二進制流。
使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如socket、http等等。
響應端基於什麼機制來接收請求?
監聽符合協議的端口。
怎麼將流還原爲傳輸格式的?
同問題3。
處理完畢後怎麼迴應?
遵循JMS API生成消息,並寫入JMS Queue中。
基於JMS此類機制實現遠程通訊的例子有Spring-Intergration、Mule、Lingo等等。
Mina
Mina是Apache提供的通訊框架,在之前一直沒有提到網絡IO這塊,之前提及的框架或library基本都是基於BIO的,而Mina是採用 NIO的,NIO在併發量增長時對比BIO而言會有明顯的性能提升,而java性能的提升,與其NIO這塊與OS的緊密結合是有不小的關係的。
是基於什麼協議實現的?
基於純粹的Socket+NIO。
怎麼發起請求?
通過Mina提供的Client API。
怎麼將請求轉化爲符合協議的格式的?
Mina遵循java串行化機制對請求對象進行序列化。
使用什麼傳輸協議傳輸?
支持多種傳輸協議,例如socket、http等等。
響應端基於什麼機制來接收請求?
以NIO的方式監聽協議端口。
怎麼將流還原爲傳輸格式的?
遵循java串行化機制對請求對象進行反序列化。
處理完畢後怎麼迴應?
遵循Mina API進行返回。
MINA是NIO方式的,因此支持異步調用是毫無懸念的。
EJB
EJB最突出的在於其分佈式,EJB採用的是ORMI協議,和RMI協議是差不多的,但EJB在分佈式通訊的安全控制、transport pool、smart proxy等方面的突出使得其在分佈式領域是不可忽視的力量。
是基於什麼協議實現的?
基於ORMI協議。
怎麼發起請求?
EJB調用。
怎麼將請求轉化爲符合協議的格式的?
遵循java串行化機制對請求對象進行序列化。
使用什麼傳輸協議傳輸?
Socket。
響應端基於什麼機制來接收請求?
監聽協議端口。
怎麼將流還原爲傳輸格式的?
遵循java串行化機制對請求對象進行反序列化。
處理完畢後怎麼迴應?
直接返回處理對象即可。
在之前的分佈式服務框架系列的文章中對於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 (各種協議的私有序列化機制等)、各種框架的實現原理(傳輸格式、如何將傳輸格式轉化爲流的、如何將請求信息轉化爲傳輸格式的、如何接收流的、如何將流還原爲傳輸格式的等等),要精通其中的哪些東西,得根據實際需求來決定了,只有在瞭解了原理的情況下才能很容易的做出選擇,甚至可以根據需求做私有的遠程通訊協議,對於從事分佈式服務平臺或開發較大型的分佈式應用的人而言,我覺得至少上面提及的知識點是需要比較瞭解的。