您好,登錄后才能下訂單哦!
這篇文章主要講解了“web中遠(yuǎn)程對(duì)象調(diào)用怎么理解”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“web中遠(yuǎn)程對(duì)象調(diào)用怎么理解”吧!
要說(shuō)“遠(yuǎn)程對(duì)象”,必先說(shuō)“遠(yuǎn)程調(diào)用”,也就是RPC。比較著名的RPC框架有,最近很火的gRPC,也就是Google開(kāi)源的RPC。另外還有Facebook開(kāi)源的Thrift等等……我廠內(nèi)部也有很多RPC框架,琳瑯滿目不暇接。Java在JDK里面也支持RMI(Remote Method Invoke: 遠(yuǎn)程方法請(qǐng)求)功能,也可以視為一種RPC,但實(shí)際上這個(gè)更像我們現(xiàn)在要討論的“遠(yuǎn)程對(duì)象調(diào)用”。
在諸多的RPC中,我們都基本認(rèn)為是通過(guò)網(wǎng)絡(luò),對(duì)運(yùn)行在另外一個(gè)進(jìn)程(或者電腦)里的某個(gè)函數(shù),發(fā)起一次調(diào)用請(qǐng)求。既然是一次函數(shù)調(diào)用,那么我們自然要傳入?yún)?shù),然后期望獲得返回值。在這個(gè)過(guò)程中,我們往往只需要輸入:函數(shù)名+參數(shù),RPC就能找到一個(gè)遠(yuǎn)程的進(jìn)程,去執(zhí)行對(duì)應(yīng)的函數(shù),然后傳入目標(biāo)參數(shù)。在這個(gè)過(guò)程里,執(zhí)行這個(gè)函數(shù)的進(jìn)程,會(huì)被認(rèn)為是無(wú)狀態(tài)的,所有的輸出,都僅與輸入的參數(shù)有關(guān),除非有一部分狀態(tài)是記錄在數(shù)據(jù)庫(kù)(持久化設(shè)備)上的。因此,計(jì)算的過(guò)程(算法),和計(jì)算的數(shù)據(jù),實(shí)際上分離的,這些計(jì)算所需的數(shù)據(jù),要么來(lái)源于參數(shù),要么是數(shù)據(jù)庫(kù)設(shè)備。而被請(qǐng)求的函數(shù),以及裝載這個(gè)函數(shù)的容器——進(jìn)程,是不保證任何的狀態(tài)維護(hù)能力的。
而“遠(yuǎn)程對(duì)象調(diào)用”,正是在“狀態(tài)”這個(gè)環(huán)節(jié)上,和RPC不同——它是由框架去保證某種狀態(tài)的。當(dāng)我們發(fā)起一個(gè)遠(yuǎn)程對(duì)象調(diào)用的時(shí)候,是需要首先“找到”一個(gè)遠(yuǎn)程對(duì)象,然后再發(fā)起“方法”(成員函數(shù))調(diào)用。這和RPC就產(chǎn)生了兩個(gè)明顯的區(qū)別:
我們需要用某種手段定位到對(duì)象,而不是僅僅用一個(gè)函數(shù)名。對(duì)象是一個(gè)更復(fù)雜的遠(yuǎn)程概念,因?yàn)橛锌赡芡瑢儆谝粋€(gè)類(class),而存在多個(gè)狀態(tài)一致或不一致的對(duì)象,在遠(yuǎn)程的機(jī)器上存在。我們就不能僅僅通過(guò)一個(gè)固定的路由標(biāo)志(比如類名)去找一個(gè)這樣的對(duì)象。遠(yuǎn)程對(duì)象的路由方式成為不同“遠(yuǎn)程對(duì)象調(diào)用”框架之間的一個(gè)顯著區(qū)別。
我們并不需要把所有的數(shù)據(jù),在每次請(qǐng)求時(shí)都通過(guò)參數(shù)發(fā)給遠(yuǎn)程對(duì)象,因?yàn)閷?duì)于同一個(gè)遠(yuǎn)程對(duì)象來(lái)說(shuō),它是可以包含大量過(guò)程狀態(tài)的。我們只要找到正確的遠(yuǎn)程對(duì)象,就能獲得之前操作所造成的結(jié)果狀態(tài)。有遠(yuǎn)程對(duì)象往往是生存在進(jìn)程的內(nèi)存中,所以對(duì)于訪問(wèn)自己的狀態(tài)數(shù)據(jù),會(huì)非??焖?,這對(duì)于有延遲壓力的程序來(lái)說(shuō),是非常有用的。
所以,遠(yuǎn)程對(duì)象調(diào)用,最大的特點(diǎn),就是數(shù)據(jù)和計(jì)算是合并在一起的——這很好的提高了使用面向?qū)ο缶幊痰谋憷?,也大大降低了遠(yuǎn)程調(diào)用中因?yàn)閿?shù)據(jù)拉取產(chǎn)生的延遲。
在傳統(tǒng)的“請(qǐng)求-響應(yīng)”為基礎(chǔ)的分布式服務(wù)器中,最常見(jiàn)的數(shù)據(jù)系統(tǒng)是:接入-邏輯-緩存-數(shù)據(jù)庫(kù) 這樣一個(gè)四層結(jié)構(gòu)。為了讓承擔(dān)計(jì)算壓力的“邏輯”模塊能分布到不同的進(jìn)程上,我們往往會(huì)把“邏輯”模塊做成“無(wú)狀態(tài)”的,這樣我們就可以隨意的啟動(dòng)、停止任何一個(gè)邏輯模塊的進(jìn)程,而不需要擔(dān)心因此丟失用戶數(shù)據(jù)。但是這樣做,邏輯模塊是輕松了,承擔(dān)狀態(tài)存儲(chǔ)的“緩存-數(shù)據(jù)庫(kù)”哥倆壓力就大了。因?yàn)槊恳粋€(gè)數(shù)據(jù)操作,都需要去從他們這里讀取數(shù)據(jù),然后再回寫(xiě)結(jié)果(如果有數(shù)據(jù)修改操作的話)。
一個(gè)客戶端程序,想要訪問(wèn)一個(gè)EJB對(duì)象,一般需要使用一個(gè)叫做JNDI的API,來(lái)具體連接到EJB對(duì)象上。JNDI的全稱是Java Naming and Directory Inerface,基本等于我們常說(shuō)的名字、目錄服務(wù)接口。Java通過(guò)一套API規(guī)范,來(lái)統(tǒng)一各種目錄服務(wù)器的使用方法。所有的J2EE容器,都必須提供一個(gè)JNDI服務(wù),而客戶端程序則通過(guò)使用J2EE容器提供的JNDI來(lái)訪問(wèn)容器內(nèi)的EJB對(duì)象。JNDI的使用方法,基本上就是輸入一個(gè)字符串,然后API會(huì)返回給你一個(gè)對(duì)象。在J2EE的環(huán)境里,這個(gè)對(duì)象就是EJB對(duì)象的Home接口對(duì)象(對(duì)應(yīng)遠(yuǎn)程EJB對(duì)象的一個(gè)映像,也叫樁對(duì)象)。代碼類似:
Context ctx = new InitialContext(env); Object ejbHome = ctx.lookup(“java:comp/env/ejb/HelloBean”); HelloHome empHome = (HelloHome) PortableRemoteObject.narrow (ejbHome, HelloHome.class);
輸入lookup()函數(shù)的字符串,是用戶可以自己定義的任何內(nèi)容,只要在對(duì)應(yīng)的EJB容器里面登記了這個(gè)對(duì)應(yīng)關(guān)系即可。從這個(gè)代碼我們可以看到,如果EJB想要做容災(zāi)、負(fù)載均衡等功能,是完全可以通過(guò)ctx.lookup()
這個(gè)接口來(lái)實(shí)現(xiàn)的。另外,遠(yuǎn)程對(duì)象的Home接口(樁代碼)是需要預(yù)先部署在客戶端測(cè),在上面的例子里是HelloHome.class這個(gè)類。而EJB對(duì)象的這個(gè)Home接口類,是由EJB工具,自動(dòng)通過(guò)來(lái)源的EJB對(duì)象類定義生成的。對(duì)比CORBA,Thrift等技術(shù),EJB可以直接用.java源代碼代替IDL定義,然后自動(dòng)生成樁代碼,這確實(shí)是簡(jiǎn)便很多。
EJB規(guī)范把遠(yuǎn)程對(duì)象定義為三種:無(wú)狀態(tài)會(huì)話Bean,有狀態(tài)會(huì)話Bean,消息驅(qū)動(dòng)Bean。這意味著EJB容器對(duì)于EJB對(duì)象的生命周期是有管理的。其中無(wú)狀態(tài)會(huì)話Bean和消息驅(qū)動(dòng)Bean的聲明周期是類似的,都是來(lái)一個(gè)請(qǐng)求(消息驅(qū)動(dòng)的意思是每來(lái)一個(gè)JMS消息),就可能new一個(gè)Bean對(duì)象。當(dāng)然也可能不是每次請(qǐng)求都新建對(duì)象,總之容器不保證會(huì)保持Bean對(duì)象的生存周期,這樣容器可以根據(jù)負(fù)載壓力,靈活的管理眾多的Bean對(duì)象。而最特別的是“有狀態(tài)會(huì)話Bean”,容器會(huì)根據(jù)客戶端的會(huì)話狀態(tài)(和客戶端的context對(duì)象對(duì)應(yīng)),來(lái)保持Bean對(duì)象,也就是說(shuō),每個(gè)客戶端context對(duì)應(yīng)一個(gè)有狀態(tài)Bean。如果你用這個(gè)客戶端context,發(fā)起多次lookup()查找,訪問(wèn)的那個(gè)EJB對(duì)象都將會(huì)是同一個(gè)。這對(duì)于需要保持登錄狀態(tài)的服務(wù),就非常方便了??蛻魺o(wú)需自己去維持一個(gè)遠(yuǎn)程對(duì)象的生命周期,而能得到狀態(tài)保存的功能。
最后說(shuō)說(shuō)EJB的部署配置,以前的EJB容器部署異常復(fù)雜。除了需要寫(xiě)一個(gè)繼承于特定基類的業(yè)務(wù)JAVA類外,還要配置很多細(xì)節(jié)。而EJB3.0之后,通過(guò)JAVA注解功能(Annotation),這些配置都可以和源代碼寫(xiě)到一起,而業(yè)務(wù)JAVA類也無(wú)需集成特定的接口和類型,可以是任何一個(gè)普通的類(POJO),只是需要加上一些特定的注釋即可。EJB容器提供工具對(duì)這些加了EJB注釋的JAVA類進(jìn)行處理,一方面把這個(gè)JAVA類自動(dòng)部署到容器中,另一方面生成客戶端的Home接口類文件,供用戶發(fā)布(拷貝)到需要使用的客戶方服務(wù)器上去。而一些EJB容器(如Weblogic)還提供了Eclipse(IDE)的圖形界面工具,讓整個(gè)過(guò)程幾乎都不在需要編寫(xiě)額外的配置和命令行操作。
WCF全稱Windows Communication Foundation,是微軟發(fā)布的用于構(gòu)建面向服務(wù)的應(yīng)用程序框架。這套框架的底層是Windows的COM+技術(shù),而編程接口則更多的使用C#語(yǔ)言/VB語(yǔ)言和.Net平臺(tái)。這和EJB有一定的類似,差別就是WCF中的遠(yuǎn)程對(duì)象,不需要一個(gè)像JVM那樣的虛擬機(jī),而是結(jié)合在WINDOWS操作系統(tǒng)里。
無(wú)獨(dú)有偶,WCF的遠(yuǎn)程接口定義,也是直接使用C#/VB代碼,加上類似注解的“特性”(Attribute)功能注釋,標(biāo)注在一個(gè)定義好的接口(Interface)上來(lái)組成的。具體的業(yè)務(wù)實(shí)現(xiàn)類,只要“實(shí)現(xiàn)”定義的這個(gè)接口就可以了,和一個(gè)普通的類沒(méi)有任何差別。和EJB的差別是,我們還是需要寫(xiě)一段XML配置,把這個(gè)遠(yuǎn)程對(duì)象的接口和查找字符串,注冊(cè)到萬(wàn)能的IIS服務(wù)器里面。一旦注冊(cè)完成,就可以通過(guò)URL:http://xx.xx.xx.xx/servicesname/service.svc
這樣的字符串去訪問(wèn)了。同時(shí),如果客戶端想要訪問(wèn)這個(gè)遠(yuǎn)程對(duì)象,則需要使用svcuitl.exe這個(gè)工具,輸入剛剛注冊(cè)的那個(gè)URL,就可以生成對(duì)應(yīng)的客戶端樁代碼庫(kù)。客戶端可以直接new這個(gè)新建立的樁類型對(duì)象,然后直接調(diào)用其方法,就和調(diào)用本地對(duì)象的方法一樣。
// Create a client. CalculatorClient client = new CalculatorClient(); // Call the Add service operation. double value1 = 100.00D; double value2 = 15.99D; double result = client.Add(value1, value2); Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
當(dāng)然,如果你想連接不同的服務(wù)器,還是有機(jī)會(huì)的,一位內(nèi)生成的客戶端代碼,會(huì)使用一個(gè)配置文件。在里面可以修改遠(yuǎn)程服務(wù)器的地址(還是那個(gè)注冊(cè)的URL)。
<client> <endpoint address="http://localhost/servicemodelsamples/service.svc" binding="wsHttpBinding" contract=" Microsoft.ServiceModel.Samples.ICalculator" /> </client>
你除了可以通過(guò)IIS來(lái)提供WCF的遠(yuǎn)程對(duì)象服務(wù)外,還可以自己寫(xiě)一個(gè)單獨(dú)的程序,通過(guò)定義main()來(lái)完全的控制這些遠(yuǎn)程對(duì)象,從而提供服務(wù)。另外,WCF除了通過(guò)URL直接對(duì)應(yīng)一個(gè)遠(yuǎn)程對(duì)象外,還可以通過(guò)編寫(xiě)“路由服務(wù)”,來(lái)對(duì)同一個(gè)URL的遠(yuǎn)程對(duì)象調(diào)用進(jìn)行靈活的路由。雖然WCF沒(méi)有提供類似EJB的遠(yuǎn)程對(duì)象生命周期管理功能,但是你完全可以通過(guò)WCF的服務(wù)API和路由服務(wù),來(lái)自己編碼實(shí)現(xiàn)任何形式的遠(yuǎn)程對(duì)象生命周期管理。
IBM公司的RMI-IIOP服務(wù),是以JAVA技術(shù)為基礎(chǔ)的,但是又不同于EJB的另外一套遠(yuǎn)程對(duì)象技術(shù)。這套技術(shù)更接近于以JAVA為基礎(chǔ)實(shí)現(xiàn)的CORBA體系。這個(gè)技術(shù)的使用標(biāo)準(zhǔn)的JAVA RMI接口(RMIInterface)作為遠(yuǎn)程對(duì)象的接口,使用JAVA的序列化、反序列化能力作為編碼能力。然后自己寫(xiě)一個(gè)main()
函數(shù),建立一個(gè)org.omg.CORBA.ORB
對(duì)象來(lái)構(gòu)造一個(gè)遠(yuǎn)程服務(wù)器。而客戶端則是通過(guò)一個(gè)字符串來(lái)定位想要訪問(wèn)的遠(yuǎn)程對(duì)象。這個(gè)字符串類似:corbaloc:iiop:1.2@localhost:8080/OurLittleClient
。我們可以看到這里面有IP和端口,還有一個(gè)編寫(xiě)服務(wù)器遠(yuǎn)程對(duì)象時(shí)注冊(cè)的字符串OurlLittleClient。我們通過(guò)rmic –iiop Server
這樣的命令行部署遠(yuǎn)程對(duì)象,然后用start java Server啟動(dòng)服務(wù)器,用start java Client啟動(dòng)客戶機(jī)。這些命名,都是包含在IBM Developer Kit for Java technology v1.3.1里面的。我們可以發(fā)現(xiàn),RMI-IIOP是一個(gè)更加原始的遠(yuǎn)程對(duì)象方案,基本上就是一個(gè)CORBA的API實(shí)現(xiàn)的組合。使用起來(lái)有點(diǎn)繁瑣,但是好處是不需要學(xué)習(xí)和部署復(fù)雜的容器服務(wù),可以完全自己編碼去實(shí)現(xiàn)一套遠(yuǎn)程對(duì)象服務(wù)。這里沒(méi)有限定你使用什么方法去定位查找遠(yuǎn)程對(duì)象,也沒(méi)有限定你怎么管理遠(yuǎn)程對(duì)象的生命周期,一切都由開(kāi)發(fā)者自己去編寫(xiě)實(shí)現(xiàn)。
規(guī)范 | 遠(yuǎn)程對(duì)象定位 | 遠(yuǎn)程對(duì)象生命周期管理 | 服務(wù)器部署 |
---|---|---|---|
EJB | JNDI路徑字符串查找 | 自動(dòng)管理,帶會(huì)話狀態(tài)對(duì)象 | 使用容器服務(wù) |
WCF | URL、路由服務(wù) | 無(wú) | 部署到IIS或自寫(xiě)main() |
RMI-IIOP | COBRA URL定位 | 無(wú) | 自寫(xiě)main() |
在對(duì)象定位的選擇上,通過(guò)字符串查找已經(jīng)是標(biāo)準(zhǔn),而復(fù)雜的自定義路由也可以隱藏在這個(gè)查找操作下面。遠(yuǎn)程對(duì)象的生命周期管理,實(shí)際上是對(duì)服務(wù)器資源的管理,除了EJB有容器支持以外,其他的方案都比較少提供這樣的能力,說(shuō)明這一塊是比較困難的。服務(wù)器部署方面,可以讓用戶以API自己寫(xiě)main()去構(gòu)建服務(wù)器,提供了極大的靈活性。
通過(guò)上面的分析,我們可以發(fā)現(xiàn),遠(yuǎn)程對(duì)象的生命周期管理,是一個(gè)比較重大且復(fù)雜的課題。我們要保證這樣的生命周期管理程序,能有一個(gè)通用的策略,來(lái)保持各種業(yè)務(wù)情況下的服務(wù)器資源穩(wěn)定,是比較困難的。而且在分布式系統(tǒng)的情況下,為了負(fù)載均衡,還要把同樣類型的遠(yuǎn)程對(duì)象,部署到不同的進(jìn)程上,這就引入了一個(gè)新的問(wèn)題:數(shù)據(jù)一致性。
遠(yuǎn)程對(duì)象的生命周期,除了占用服務(wù)器的內(nèi)存資源外,還會(huì)占用記錄其地址的路由空間,檢查維護(hù)生命周期的CPU運(yùn)算時(shí)間。如果我們提供自動(dòng)化的對(duì)象生命周期管理,勢(shì)必就需要在客戶使用的時(shí)候,提供這方面的教育,以及防止客戶使用錯(cuò)誤、過(guò)載等情況下對(duì)象管理失效的防御性策略。所以即便是EJB容器,也僅僅提供了非常簡(jiǎn)單的生命周期管理策略:會(huì)話狀態(tài)、無(wú)狀態(tài)這兩種。
對(duì)于一般的互聯(lián)網(wǎng)應(yīng)用,只有EJB這兩種生命周期管理的遠(yuǎn)程對(duì)象,基本上是夠用的。因?yàn)橐话愕幕ヂ?lián)網(wǎng)應(yīng)用,大部分?jǐn)?shù)據(jù)都是持久化數(shù)據(jù),需要讀寫(xiě)數(shù)據(jù)庫(kù)。臨時(shí)狀態(tài)數(shù)據(jù)一般來(lái)說(shuō)不多,主要是用戶登錄后的產(chǎn)生的一些過(guò)程數(shù)據(jù),有一個(gè)“會(huì)話(Session)”類型的生命周期就足夠了。但是,如果我們的業(yè)務(wù)是網(wǎng)絡(luò)游戲,那么這么簡(jiǎn)單的生命周期就是完全不夠的,因?yàn)橛螒蛑杏写罅康呐R時(shí)狀態(tài),比如組隊(duì)的狀態(tài),玩家所在房間的狀態(tài),關(guān)卡副本的狀態(tài)等等。這些臨時(shí)狀態(tài),都是需要我們通過(guò)業(yè)務(wù)邏輯代碼,來(lái)控制和管理所對(duì)應(yīng)的對(duì)象生命周期的。所以一個(gè)適合游戲的遠(yuǎn)程對(duì)象系統(tǒng),需要提供讓客戶端程序來(lái)選擇,“新建/初始化”和“銷毀”遠(yuǎn)程對(duì)象的能力。
在對(duì)遠(yuǎn)程對(duì)象進(jìn)行管理的時(shí)候,我們常常會(huì)用到一種叫“對(duì)象池”的技術(shù),使用這種技術(shù)避免頻繁的新建和銷毀對(duì)象。但是如果這些對(duì)象的是帶狀態(tài)的,那么我們的“池”就必須帶索引,并且對(duì)象也必須有一個(gè)key。同時(shí)我們的對(duì)象還需要有一個(gè)“reset”的重置方法,用來(lái)讓對(duì)象回歸到初始化狀態(tài)。
在分布式的系統(tǒng)下,我們的對(duì)象池因?yàn)槭欠謩e存放在不同的機(jī)器上,所以其一致性的維護(hù)往往是比較困難的。但是,我們可以把這個(gè)問(wèn)題,轉(zhuǎn)換成構(gòu)建一個(gè)“分布式對(duì)象池”的問(wèn)題。假如每個(gè)對(duì)象池,都按KEY的某個(gè)規(guī)律,如一致性哈希,存放不同的對(duì)象。那么只要在遠(yuǎn)程調(diào)用發(fā)起的時(shí)候,也就是通過(guò)lookup()查找遠(yuǎn)程對(duì)象的時(shí)候,把請(qǐng)求導(dǎo)向到對(duì)象所在進(jìn)程,那么就能很方便的從本地進(jìn)程對(duì)象池中獲得對(duì)象。遠(yuǎn)程對(duì)象的“定位”和“一致性”在查找對(duì)象這個(gè)環(huán)節(jié)結(jié)合起來(lái),是一個(gè)非常好的想法。這樣能讓遠(yuǎn)程狀態(tài)對(duì)象的使用進(jìn)一步簡(jiǎn)化,用戶完全無(wú)需關(guān)心遠(yuǎn)程對(duì)象在什么地方,又能快速的訪問(wèn)到正確的對(duì)象。
[擴(kuò)容下的遠(yuǎn)程對(duì)象遷移]
當(dāng)分布式的對(duì)象容器出現(xiàn)部分進(jìn)程故障,或者需要?jiǎng)討B(tài)擴(kuò)容的時(shí)候,只要我們針對(duì)對(duì)象查找的數(shù)據(jù)做某種程度的數(shù)據(jù)搬遷,或者緩存清理,就能很容易的實(shí)現(xiàn)對(duì)象的重新分布。如果對(duì)象同時(shí)能夠支持持久化,那么這種數(shù)據(jù)搬遷,只需要簡(jiǎn)單的讓對(duì)象寫(xiě)入持久化。然后在新的機(jī)器上,通過(guò)緩存建立的策略,從持久化設(shè)備讀取出對(duì)象即可。
感謝各位的閱讀,以上就是“web中遠(yuǎn)程對(duì)象調(diào)用怎么理解”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)web中遠(yuǎn)程對(duì)象調(diào)用怎么理解這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。