基本原理
要實(shí)現網(wǎng)絡(luò )機器間的通訊,首先得來(lái)看看計算機系統網(wǎng)絡(luò )通信的基本原理,在底層層面去看,網(wǎng)絡(luò )通信需要做的就是將流從一臺計算機傳輸到另外一臺計算機,基于傳輸協(xié)議和網(wǎng)絡(luò )IO來(lái)實(shí)現,其中傳輸協(xié)議比較出名的有http、tcp、udp等等,http、tcp、udp都是在基于Socket概念上為某類(lèi)應用場(chǎng)景而擴展出的傳輸協(xié)議,網(wǎng)絡(luò )IO,主要有bio、nio、aio三種方式,所有的分布式應用通訊都基于這個(gè)原理而實(shí)現,只是為了應用的易用,各種語(yǔ)言通常都會(huì )提供一些更為貼近應用易用的應用層協(xié)議。
應用級協(xié)議
遠程服務(wù)通訊,需要達到的目標是在一臺計算機發(fā)起請求,另外一臺機器在接收到請求后進(jìn)行相應的處理并將結果返回給請求端,這其中又會(huì )有諸如one way request、同步請求、異步請求等等請求方式,按照網(wǎng)絡(luò )通信原理,需要實(shí)現這個(gè)需要做的就是將請求轉換成流,通過(guò)傳輸協(xié)議傳輸至遠端,遠端計算機在接收到請求的流后進(jìn)行處理,處理完畢后將結果轉化為流,并通過(guò)傳輸協(xié)議返回給調用端。
原理是這樣的,但為了應用的方便,業(yè)界推出了很多基于此原理之上的應用級的協(xié)議,使得大家可以不用去直接操作這么底層的東西,通常應用級的遠程通信協(xié)議會(huì )提供:
為了避免直接做流操作這么麻煩,提供一種更加易用或貼合語(yǔ)言的標準傳輸格式;
網(wǎng)絡(luò )通信機制的實(shí)現,就是替你完成了將傳輸格式轉化為流,通過(guò)某種傳輸協(xié)議傳輸至遠端計算機,遠端計算機在接收到流后轉化為傳輸格式,并進(jìn)行存儲或以某種方式通知遠端計算機。
所以在學(xué)習應用級的遠程通信協(xié)議時(shí),我們可以帶著(zhù)這幾個(gè)問(wèn)題進(jìn)行學(xué)習:
◆ 傳輸的標準格式是什么?
◆ 怎么樣將請求轉化為傳輸的流?
◆ 怎么接收和處理流?
◆ 傳輸協(xié)議是?
不過(guò)應用級的遠程通信協(xié)議并不會(huì )在傳輸協(xié)議上做什么多大的改進(jìn),主要是在流操作方面,讓?xiě)脤由闪骱吞幚砹鞯倪@個(gè)過(guò)程更加的貼合所使用的語(yǔ)言或標準,至于傳輸協(xié)議則通常都是可選的,在java領(lǐng)域中知名的有:RMI、XML-RPC、Binary-RPC、SOAP、CORBA、JMS,來(lái)具體的看看這些遠程通信的應用級協(xié)議:
RMI
RMI是個(gè)典型的為java定制的遠程通信協(xié)議,我們都知道,在single vm中,我們可以通過(guò)直接調用java object instance來(lái)實(shí)現通信,那么在遠程通信時(shí),如果也能按照這種方式當然是最好了,這種遠程通信的機制成為RPC(Remote Procedure Call),RMI正是朝著(zhù)這個(gè)目標而誕生的。
來(lái)看下基于RMI的一次完整的遠程通信過(guò)程的原理:
◆ 客戶(hù)端發(fā)起請求,請求轉交至RMI客戶(hù)端的stub類(lèi);
◆ stub類(lèi)將請求的接口、方法、參數等信息進(jìn)行序列化;
◆ 基于socket將序列化后的流傳輸至服務(wù)器端;
◆ 服務(wù)器端接收到流后轉發(fā)至相應的skelton類(lèi);
◆ skelton類(lèi)將請求的信息反序列化后調用實(shí)際的處理類(lèi);
◆ 處理類(lèi)處理完畢后將結果返回給skelton類(lèi);
◆ Skelton類(lèi)將結果序列化,通過(guò)socket將流傳送給客戶(hù)端的stub;
◆ stub在接收到流后反序列化,將反序列化后的Java Object返回給調用者。
根據原理來(lái)回答下之前學(xué)習應用級協(xié)議帶著(zhù)的幾個(gè)問(wèn)題:
◆ 傳輸的標準格式是什么?
是Java ObjectStream。
◆ 怎么樣將請求轉化為傳輸的流?
基于Java串行化機制將請求的java object信息轉化為流。
◆ 怎么接收和處理流?
根據采用的協(xié)議啟動(dòng)相應的監聽(tīng)端口,當有流進(jìn)入后基于Java串行化機制將流進(jìn)行反序列化,并根據RMI協(xié)議獲取到相應的處理對象信息,進(jìn)行調用并處理,處理完畢后的結果同樣基于java串行化機制進(jìn)行返回。
◆ 傳輸協(xié)議是?
Socket。
XML-RPC
XML-RPC也是一種和RMI類(lèi)似的遠程調用的協(xié)議,它和RMI的不同之處在于它以標準的xml格式來(lái)定義請求的信息(請求的對象、方法、參數等),這樣的好處是什么呢,就是在跨語(yǔ)言通訊的時(shí)候也可以使用。
來(lái)看下XML-RPC協(xié)議的一次遠程通信過(guò)程:
◆ 客戶(hù)端發(fā)起請求,按照XML-RPC協(xié)議將請求信息進(jìn)行填充;
◆ 填充完畢后將xml轉化為流,通過(guò)傳輸協(xié)議進(jìn)行傳輸;
◆ 接收到在接收到流后轉換為xml,按照XML-RPC協(xié)議獲取請求的信息并進(jìn)行處理;
◆ 處理完畢后將結果按照XML-RPC協(xié)議寫(xiě)入xml中并返回。
同樣來(lái)回答問(wèn)題:
◆ 傳輸的標準格式是?
標準格式的XML。
◆ 怎么樣將請求轉化為傳輸的流?
將XML轉化為流。
◆ 怎么接收和處理流?
通過(guò)監聽(tīng)的端口獲取到請求的流,轉化為XML,并根據協(xié)議獲取請求的信息,進(jìn)行處理并將結果寫(xiě)入XML中返回。
◆ 傳輸協(xié)議是?
Binary-RPC
Binary-RPC看名字就知道和XML-RPC是差不多的了,不同之處僅在于傳輸的標準格式由XML轉為了二進(jìn)制的格式。
同樣來(lái)回答問(wèn)題:
◆ 傳輸的標準格式是?
標準格式的二進(jìn)制文件。
◆ 怎么樣將請求轉化為傳輸的流?
將二進(jìn)制格式文件轉化為流。
◆ 怎么接收和處理流?
通過(guò)監聽(tīng)的端口獲取到請求的流,轉化為二進(jìn)制文件,根據協(xié)議獲取請求的信息,進(jìn)行處理并將結果寫(xiě)入XML中返回。
◆ 傳輸協(xié)議是?
Http。
SOAP
SOAP原意為Simple Object Access Protocol,是一個(gè)用于分布式環(huán)境的、輕量級的、基于XML進(jìn)行信息交換的通信協(xié)議,可以認為SOAP是XML RPC的高級版,兩者的原理完全相同,都是http+XML,不同的僅在于兩者定義的XML規范不同,SOAP也是Webservice采用的服務(wù)調用協(xié)議標準,因此在此就不多加闡述了。
CORBA
Common Object Request Broker Architecture(公用對象請求代理[調度]程序體系結構),是一組用來(lái)定義“分布式對象系統”的標準,由OMG(Object Menagement Group)作為發(fā)起和標準制定單位。CORBA的目的是定義一套協(xié)議,符合這個(gè)協(xié)議的對象可以互相交互,不論它們是用什么樣的語(yǔ)言寫(xiě)的,不論它們運行于什么樣的機器和操作系統。
CORBA在我看來(lái)是個(gè)類(lèi)似于SOA的體系架構,涵蓋可選的遠程通信協(xié)議,但其本身不能列入通信協(xié)議這里來(lái)講,而且CORBA基本淘汰,再加上對CORBA也不怎么懂,在此就不進(jìn)行闡述了。
JMS
JMS呢,是實(shí)現java領(lǐng)域遠程通信的一種手段和方法,基于JMS實(shí)現遠程通信時(shí)和RPC是不同的,雖然可以做到RPC的效果,但因為不是從協(xié)議級別定義的,因此我們不認為JMS是個(gè)RPC協(xié)議,但它確實(shí)是個(gè)遠程通信協(xié)議,在其他的語(yǔ)言體系中也存在著(zhù)類(lèi)似JMS的東西,可以統一的將這類(lèi)機制稱(chēng)為消息機制,而消息機制呢,通常是高并發(fā)、分布式領(lǐng)域推薦的一種通信機制,這里的主要一個(gè)問(wèn)題是容錯(詳細見(jiàn)ErLang論文)。
來(lái)看JMS中的一次遠程通信的過(guò)程:
◆ 客戶(hù)端將請求轉化為符合JMS規定的Message;
◆ 通過(guò)JMS API將Message放入JMS Queue或Topic中;
◆ 如為JMS Queue,則發(fā)送中相應的目標Queue中,如為T(mén)opic,則發(fā)送給訂閱了此Topic的JMS Queue。
處理端則通過(guò)輪訓JMS Queue,來(lái)獲取消息,接收到消息后根據JMS協(xié)議來(lái)解析Message并處理。
回答問(wèn)題:
◆ 傳輸的標準格式是?
JMS規定的Message。
◆ 怎么樣將請求轉化為傳輸的流?
將參數信息放入Message中即可。
◆ 怎么接收和處理流?
輪訓JMS Queue來(lái)接收Message,接收到后進(jìn)行處理,處理完畢后仍然是以Message的方式放入Queue中發(fā)送或Multicast。
◆ 傳輸協(xié)議是?
不限。
基于JMS也是常用的實(shí)現遠程異步調用的方法之一。
當然,在上面的原理中并沒(méi)有介紹到所有的java領(lǐng)域可選的遠程通信協(xié)議了,例如還有EJB采用的ORMI、Spring自己定義的一個(gè)簡(jiǎn)單的Http Invoker等等。
看完原理后我們再來(lái)看看目前java領(lǐng)域可用于實(shí)現遠程通訊的框架或library,知名的有:JBoss-Remoting、Spring- Remoting、Hessian、Burlap、XFire(Axis)、ActiveMQ、Mina、Mule、EJB3等等,來(lái)對每種做個(gè)簡(jiǎn)單的介紹和評價(jià),其實(shí)呢,要做分布式服務(wù)框架,這些東西都是要有非常深刻的了解的,因為分布式服務(wù)框架其實(shí)是包含了解決分布式領(lǐng)域以及應用層面領(lǐng)域兩方面問(wèn)題的。
當然,你也可以自己根據遠程網(wǎng)絡(luò )通信原理(transport protocol+Net IO)去實(shí)現自己的通訊框架或library。
那么在了解這些遠程通訊的框架或library時(shí),會(huì )帶著(zhù)什么問(wèn)題去學(xué)習呢?
◆ 是基于什么協(xié)議實(shí)現的?
◆ 怎么發(fā)起請求?
◆ 怎么將請求轉化為符合協(xié)議的格式的?
◆ 使用什么傳輸協(xié)議傳輸?
◆ 響應端基于什么機制來(lái)接收請求?
◆ 怎么將流還原為傳輸格式的?
JBoss-Remoting
Jboss-remoting是由jboss編寫(xiě)的一個(gè)java領(lǐng)域的遠程通訊框架,基于此框架,可以很簡(jiǎn)單的實(shí)現基于多種傳輸協(xié)議的java對象的RPC。
直接來(lái)回答問(wèn)題:
◆ 是基于什么協(xié)議實(shí)現的?
JBoss-Remoting是個(gè)通訊框架,因此它支持多種協(xié)議方式的通信,例如純粹的socket+io方式、rmi方式、http+io方式等。
◆ 怎么發(fā)起請求?
在JBoss-Remoting中,只需將需要發(fā)起的請求參數對象傳入jboss-remoting的InvocationRequest對象即可,也可根據協(xié)議基于InvocationRequest封裝符合需求的InvocationRequest對象。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
JBoss-Remoting基于Java串行化機制或JBoss自己的串行化實(shí)現來(lái)將請求轉化為對象字節流。
◆ 使用什么傳輸協(xié)議傳輸?
支持多種傳輸協(xié)議,例如socket、http等。
◆ 響應端基于什么機制來(lái)接收請求?
響應端只需將自己的處理對象注冊到JBoss-Remoting提供的server端的Connector對象中即可。
◆ 怎么將流還原為傳輸格式的?
JBoss-Remoting基于java串行化機制或jboss自己的串行化實(shí)現來(lái)將請求信息還原為java對象。
◆ 處理完畢后怎么回應?
處理完畢后將結果對象直接返回即可,jboss-remoting會(huì )將此對象按照協(xié)議進(jìn)行序列化,返回至調用端。
另外,jboss-remoting支持多種通信方式,例如同步/異步/單向通信等。
Spring-Remoting
Spring-remoting是Spring提供java領(lǐng)域的遠程通訊框架,基于此框架,同樣也可以很簡(jiǎn)單的將普通的spring bean以某種遠程協(xié)議的方式來(lái)發(fā)布,同樣也可以配置spring bean為遠程調用的bean。
◆ 是基于什么協(xié)議實(shí)現的?
和JBoss-Remoting一樣,作為一個(gè)遠程通訊的框架,Spring通過(guò)集成多種遠程通訊的library,從而實(shí)現了對多種協(xié)議的支持,例如rmi、http+io、xml-rpc、binary-rpc等。
◆ 怎么發(fā)起請求?
在Spring中,由于其對于遠程調用的bean采用的是proxy實(shí)現,發(fā)起請求完全是通過(guò)服務(wù)接口調用的方式。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
Spring按照協(xié)議方式將請求的對象信息轉化為流,例如Spring Http Invoker是基于Spring自己定義的一個(gè)協(xié)議來(lái)實(shí)現的,傳輸協(xié)議上采用的為http,請求信息是基于java串行化機制轉化為流進(jìn)行傳輸。
◆ 使用什么傳輸協(xié)議傳輸?
支持多種傳輸協(xié)議,例如rmi、http等等。
◆ 響應端基于什么機制來(lái)接收請求?
響應端遵循協(xié)議方式來(lái)接收請求,對于使用者而言,則只需通過(guò)spring的配置方式將普通的spring bean配置為響應端或者說(shuō)提供服務(wù)端。
◆ 怎么將流還原為傳輸格式的?
按照協(xié)議方式來(lái)進(jìn)行還原。
◆ 處理完畢后怎么回應?
處理完畢后直接返回即可,spring-remoting將根據協(xié)議方式來(lái)做相應的序列化。
Hessian
Hessian是由caucho提供的一個(gè)基于binary-RPC實(shí)現的遠程通訊library。
◆ 是基于什么協(xié)議實(shí)現的?
基于Binary-RPC協(xié)議實(shí)現。
◆ 怎么發(fā)起請求?
需通過(guò)Hessian本身提供的API來(lái)發(fā)起請求。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
Hessian通過(guò)其自定義的串行化機制將請求信息進(jìn)行序列化,產(chǎn)生二進(jìn)制流。
◆ 使用什么傳輸協(xié)議傳輸?
Hessian基于Http協(xié)議進(jìn)行傳輸。
◆ 響應端基于什么機制來(lái)接收請求?
響應端根據Hessian提供的API來(lái)接收請求。
◆ 怎么將流還原為傳輸格式的?
Hessian根據其私有的串行化機制來(lái)將請求信息進(jìn)行反序列化,傳遞給使用者時(shí)已是相應的請求信息對象了。
◆ 處理完畢后怎么回應?
Burlap
Burlap也是有caucho提供,它和hessian的不同在于,它是基于XML-RPC協(xié)議的。
◆ 是基于什么協(xié)議實(shí)現的?
基于XML-RPC協(xié)議實(shí)現。
◆ 怎么發(fā)起請求?
根據Burlap提供的API。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
將請求信息轉化為符合協(xié)議的XML格式,轉化為流進(jìn)行傳輸。
◆ 使用什么傳輸協(xié)議傳輸?
Http協(xié)議。
◆ 響應端基于什么機制來(lái)接收請求?
監聽(tīng)Http請求。
◆ 怎么將流還原為傳輸格式的?
根據XML-RPC協(xié)議進(jìn)行還原。
◆ 處理完畢后怎么回應?
返回結果寫(xiě)入XML中,由Burlap返回至調用端。
XFire、Axis
XFire、Axis是Webservice的實(shí)現框架,WebService可算是一個(gè)完整的SOA架構實(shí)現標準了,因此采用XFire、Axis這些也就意味著(zhù)是采用webservice方式了。
◆ 是基于什么協(xié)議實(shí)現的?
基于SOAP協(xié)議。
◆ 怎么發(fā)起請求?
獲取到遠端service的proxy后直接調用。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
將請求信息轉化為遵循SOAP協(xié)議的XML格式,由框架轉化為流進(jìn)行傳輸。
◆ 使用什么傳輸協(xié)議傳輸?
Http協(xié)議。
◆ 響應端基于什么機制來(lái)接收請求?
監聽(tīng)Http請求。
◆ 怎么將流還原為傳輸格式的?
根據SOAP協(xié)議進(jìn)行還原。
◆ 處理完畢后怎么回應?
返回結果寫(xiě)入XML中,由框架返回至調用端。
ActiveMQ
ActiveMQ是JMS的實(shí)現,基于JMS這類(lèi)消息機制實(shí)現遠程通訊是一種不錯的選擇,畢竟消息機制本身的功能使得基于它可以很容易的去實(shí)現同步/異步/單向調用等,而且消息機制從容錯角度上來(lái)說(shuō)也是個(gè)不錯的選擇,這是Erlang能夠做到容錯的重要基礎。
◆ 是基于什么協(xié)議實(shí)現的?
基于JMS協(xié)議。
◆ 怎么發(fā)起請求?
遵循JMS API發(fā)起請求。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
不太清楚,猜想應該是二進(jìn)制流。
◆ 使用什么傳輸協(xié)議傳輸?
支持多種傳輸協(xié)議,例如socket、http等等。
◆ 響應端基于什么機制來(lái)接收請求?
監聽(tīng)符合協(xié)議的端口。
◆ 怎么將流還原為傳輸格式的?
同問(wèn)題3。
◆ 處理完畢后怎么回應?
遵循JMS API生成消息,并寫(xiě)入JMS Queue中。
Mina
Mina是Apache提供的通訊框架,在之前一直沒(méi)有提到網(wǎng)絡(luò )IO這塊,之前提及的框架或library基本都是基于BIO的,而Mina是采用 NIO的,NIO在并發(fā)量增長(cháng)時(shí)對比BIO而言會(huì )有明顯的性能提升,而java性能的提升,與其N(xiāo)IO這塊與OS的緊密結合是有不小的關(guān)系的。
◆ 是基于什么協(xié)議實(shí)現的?
基于純粹的Socket+NIO。
◆ 怎么發(fā)起請求?
通過(guò)Mina提供的Client API。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
Mina遵循java串行化機制對請求對象進(jìn)行序列化。
◆ 使用什么傳輸協(xié)議傳輸?
支持多種傳輸協(xié)議,例如socket、http等等。
◆ 響應端基于什么機制來(lái)接收請求?
以NIO的方式監聽(tīng)協(xié)議端口。
◆ 怎么將流還原為傳輸格式的?
遵循java串行化機制對請求對象進(jìn)行反序列化。
◆ 處理完畢后怎么回應?
遵循Mina API進(jìn)行返回。
MINA是NIO方式的,因此支持異步調用是毫無(wú)懸念的。
EJB
EJB最突出的在于其分布式,EJB采用的是ORMI協(xié)議,和RMI協(xié)議是差不多的,但EJB在分布式通訊的安全控制、transport pool、smart proxy等方面的突出使得其在分布式領(lǐng)域是不可忽視的力量。
◆ 是基于什么協(xié)議實(shí)現的?
基于ORMI協(xié)議。
◆ 怎么發(fā)起請求?
EJB調用。
◆ 怎么將請求轉化為符合協(xié)議的格式的?
遵循java串行化機制對請求對象進(jìn)行序列化。
◆ 使用什么傳輸協(xié)議傳輸?
Socket。
◆ 響應端基于什么機制來(lái)接收請求?
監聽(tīng)協(xié)議端口。
◆ 怎么將流還原為傳輸格式的?
遵循java串行化機制對請求對象進(jìn)行反序列化。
◆ 處理完畢后怎么回應?
直接返回處理對象即可。
在之前的分布式服務(wù)框架系列的文章中對于jndi有誤導的嫌疑,在這篇blog中也順帶的提下jndi的機制,由于JNDI取決于具體的實(shí)現,在這里只能是講解下jboss的jndi的實(shí)現了。
在將對象實(shí)例綁定到j(luò )boss jnp server后,當遠程端采用context.lookup()方式獲取遠程對象實(shí)例并開(kāi)始調用時(shí),jboss jndi的實(shí)現方法是從jnp server上獲取對象實(shí)例,將其序列化回本地,然后在本地進(jìn)行反序列化,之后在本地進(jìn)行類(lèi)調用。
通過(guò)這個(gè)機制,就可以知道了,本地其實(shí)是必須有綁定到j(luò )boss上的對象實(shí)例的class的,否則反序列化的時(shí)候肯定就失敗了,而遠程通訊需要做到的是在遠程執行某動(dòng)作,并獲取到相應的結果,可見(jiàn)純粹基于JNDI是無(wú)法實(shí)現遠程通訊的。
但JNDI也是實(shí)現分布式服務(wù)框架一個(gè)很關(guān)鍵的技術(shù)點(diǎn),因為可以通過(guò)它來(lái)實(shí)現透明化的遠端和本地調用,就像ejb,另外它也是個(gè)很好的隱藏實(shí)際部署機制(就像datasource)等的方案。
總結
由上一系列的分析可知,在遠程通訊領(lǐng)域中,涉及的知識點(diǎn)還是相當的多的,例如有:通信協(xié)議(Socket/tcp/http/udp/rmi /xml-rpc etc.)、消息機制、網(wǎng)絡(luò )IO(BIO/NIO/AIO)、MultiThread、本地調用與遠程調用的透明化方案(涉及java classloader、Dynamic Proxy、Unit Test etc.)、異步與同步調用、網(wǎng)絡(luò )通信處理機制(自動(dòng)重連、廣播、異常、池處理等等)、Java Serialization (各種協(xié)議的私有序列化機制等)、各種框架的實(shí)現原理(傳輸格式、如何將傳輸格式轉化為流的、如何將請求信息轉化為傳輸格式的、如何接收流的、如何將流還原為傳輸格式的等等),要精通其中的哪些東西,得根據實(shí)際需求來(lái)決定了,只有在了解了原理的情況下才能很容易的做出選擇,甚至可以根據需求做私有的遠程通訊協(xié)議,對于從事分布式服務(wù)平臺或開(kāi)發(fā)較大型的分布式應用的人而言,我覺(jué)得至少上面提及的知識點(diǎn)是需要比較了解的。
聯(lián)系客服