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