? ? ? ? ? 大家好遣蚀,我是IT修真院北京分院第31期的學(xué)員,一枚正直純潔善良的JAVA程序員颖杏。今天給大家分享一下螟蒸,修真院官網(wǎng)JAVA任務(wù)8的深度思考——什么是rmi?為什么要使用rmi框架?
1.背景介紹
什么是RMI?
Java RMI(Remote Method Invocation)--Java的遠(yuǎn)程方法調(diào)用是Java所特有的分布式計(jì)算技術(shù),它允許運(yùn)行在一個(gè)Java虛擬機(jī)上的對象調(diào)用運(yùn)行在另一個(gè)Java虛擬機(jī)上的對象的方法艇劫,從而使Java編程人員可以方便地在網(wǎng)絡(luò)環(huán)境中作分布式計(jì)算吼驶。面向?qū)ο笤O(shè)計(jì)要求每個(gè)任務(wù)由最適合該任務(wù)的對象執(zhí)行,RMI將這個(gè)概念更深入了一步,使任務(wù)可以在最適合該任務(wù)的機(jī)器上完成蟹演。
RMI定義了一組遠(yuǎn)程接口风钻,可以用于生成遠(yuǎn)程對象【魄耄客戶機(jī)可以象調(diào)用本地對象的方法一樣用相同的語法調(diào)用遠(yuǎn)程對象骡技。
調(diào)用這樣一個(gè)對象時(shí),其參數(shù)為 "marshalled"將其從本地虛擬機(jī)發(fā)送到遠(yuǎn)程虛擬機(jī)(該遠(yuǎn)程虛擬機(jī)的參數(shù)為 "unmarshalled")上羞反。該方法終止時(shí)布朦,將編組來自遠(yuǎn)程機(jī)的結(jié)果并將結(jié)果發(fā)送到調(diào)用方的虛擬機(jī)。如果方法調(diào)用導(dǎo)致拋出異常昼窗,則該異常將指示給調(diào)用方是趴。
RMI(遠(yuǎn)程方法調(diào)用)的優(yōu)點(diǎn)
從最基本的角度看,RMI是Java的遠(yuǎn)程過程調(diào)用(RPC)機(jī)制澄惊。與傳統(tǒng)的RPC系統(tǒng)相比唆途,RMI具有若干優(yōu)點(diǎn),因?yàn)樗荍ava面向?qū)ο蠓椒ǖ囊徊糠值鹘y(tǒng)的RPC系統(tǒng)采用中性語言肛搬,所以是最普通的系統(tǒng)--它們不能提供所有可能的目標(biāo)平臺(tái)所具有的功能。 RMI以Java為核心亭敢,可與采用本機(jī)方法與現(xiàn)有系統(tǒng)相連接滚婉。這就是說,RMI可采用自然帅刀、直接和功能全面的方式為您提供分布式計(jì)算技術(shù)让腹,而這種技術(shù)可幫助您以不斷遞增和無縫的方式為整個(gè)系統(tǒng)添加Java功能。
RMI的主要優(yōu)點(diǎn)如下:
1,面向?qū)ο?RMI可將完整的對象作為參數(shù)和返回值進(jìn)行傳遞扣溺,而不僅僅是預(yù)定義的數(shù)據(jù)類型骇窍。也就是說,您可以將類似Java哈希表這樣的復(fù)雜類型作為一個(gè)參數(shù)進(jìn)行傳遞锥余。而在目前的RPC系統(tǒng)中腹纳,您只能依靠客戶機(jī)將此類對象分解成基本數(shù)據(jù)類型,然后傳遞這些數(shù)據(jù)類型驱犹,最后在服務(wù)器端重新創(chuàng)建哈希表嘲恍。RMI則不需額外的客戶程序代碼(將對象分解成基本數(shù)據(jù)類型),直接跨網(wǎng)傳遞對象雄驹。
2,可移動(dòng)屬性:RMI可將屬性(類實(shí)現(xiàn)程序)從客戶機(jī)移動(dòng)到服務(wù)器佃牛,或者從服務(wù)器移到客戶機(jī)。這樣就能具備最大的靈活性医舆,因?yàn)檎吒淖儠r(shí)只需要您編寫一個(gè)新的Java類俘侠,并將其在服務(wù)器主機(jī)上安裝一次即可象缀。
3,設(shè)計(jì)方式:對象傳遞功能使您可以在分布式計(jì)算中充分利用面向?qū)ο蠹夹g(shù)的強(qiáng)大功能,如二層和三層結(jié)構(gòu)系統(tǒng)爷速。如果您能夠傳遞屬性央星,那么您就可以在您的解決方案中使用面向?qū)ο蟮脑O(shè)計(jì)方式。所有面向?qū)ο蟮脑O(shè)計(jì)方式無不依靠不同的屬性來發(fā)揮功能惫东,如果不能傳遞完整的對象--包括實(shí)現(xiàn)和類型--就會(huì)失去設(shè)計(jì)方式上所提供的優(yōu)點(diǎn)莉给。
4,安 全:RMI使用Java內(nèi)置的安全機(jī)制保證下載執(zhí)行程序時(shí)用戶系統(tǒng)的安全。RMI使用專門為保護(hù)系統(tǒng)免遭惡意小應(yīng)用程序侵害而設(shè)計(jì)的安全管理程序廉沮,可保護(hù)您的系統(tǒng)和網(wǎng)絡(luò)免遭潛在的惡意下載程序的破壞禁谦。在情況嚴(yán)重時(shí),服務(wù)器可拒絕下載任何執(zhí)行程序废封。
5,便于編寫和使用:RMI使得Java遠(yuǎn)程服務(wù)程序和訪問這些服務(wù)程序的Java客戶程序的編寫工作變得輕松、簡單丧蘸。遠(yuǎn)程接口實(shí)際上就是Java接口漂洋。服務(wù)程序大約用三行指令宣布本身是服務(wù)程序,其它方面則與任何其它Java對象類似力喷。這種簡單方法便于快速編寫完整的分布式對象系統(tǒng)的服務(wù)程序刽漂,并快速地制做軟件的原型和早期版本,以便于進(jìn)行測試和評(píng)估弟孟。因?yàn)镽MI程序編寫簡單贝咙,所以維護(hù)也簡單。
6,可連接現(xiàn)有/原有的系統(tǒng):RMI可通過Java的本機(jī)方法接口JNI與現(xiàn)有系統(tǒng)進(jìn)行進(jìn)行交互拂募。利用RMI和JNI庭猩,您就能用Java語言編寫客戶端程序,還能使用現(xiàn)有的服務(wù)器端程序陈症。在使用RMI/JNI與現(xiàn)有服務(wù)器連接時(shí)蔼水,您可以有選擇地用Java重新編寫服務(wù)程序的任何部分,并使新的程序充分發(fā)揮Java的功能录肯。類似地趴腋,RMI可利用JDBC、在不修改使用數(shù)據(jù)庫的現(xiàn)有非Java源代碼的前提下與現(xiàn)有關(guān)系數(shù)據(jù)庫進(jìn)行交互论咏。
7,編寫一次优炬,到處運(yùn)行:RMI是Java“編寫一次,到處運(yùn)行 ”方法的一部分厅贪。任何基于RMI的系統(tǒng)均可100%地移植到任何Java虛擬機(jī)上蠢护,RMI/JDBC系統(tǒng)也不例外。如果使用RMI/JNI與現(xiàn)有系統(tǒng)進(jìn)行交互工作,則采用JNI編寫的代碼可與任何Java虛擬機(jī)進(jìn)行編譯卦溢、運(yùn)行糊余。
8,分布式垃圾收集:RMI采用其分布式垃圾收集功能收集不再被網(wǎng)絡(luò)中任何客戶程序所引用的遠(yuǎn)程服務(wù)對象秀又。與Java 虛擬機(jī)內(nèi)部的垃圾收集類似,分布式垃圾收集功能允許用戶根據(jù)自己的需要定義服務(wù)器對象贬芥,并且明確這些對象在不再被客戶機(jī)引用時(shí)會(huì)被刪除吐辙。
9,并行計(jì)算:RMI采用多線程處理方法,可使您的服務(wù)器利用這些Java線程更好地并行處理客戶端的請求蘸劈。Java分布式計(jì)算解決方案:RMI從JDK 1.1開始就是Java平臺(tái)的核心部分昏苏,因此,它存在于任何一臺(tái)1.1 Java虛擬機(jī)中威沫。所有RMI系統(tǒng)均采用相同的公開協(xié)議贤惯,所以,所有Java 系統(tǒng)均可直接相互對話棒掠,而不必事先對協(xié)議進(jìn)行轉(zhuǎn)換孵构。
2.知識(shí)剖析
RMI原理及其示意圖
方法調(diào)用從客戶對象經(jīng)占位程序(Stub)、遠(yuǎn)程引用層(Remote Reference Layer)和傳輸層(Transport Layer)向下烟很,傳遞給主機(jī)颈墅,然后再次經(jīng)傳 輸層,向上穿過遠(yuǎn)程調(diào)用層和骨干網(wǎng)(Skeleton)雾袱,到達(dá)服務(wù)器對象恤筛。 占位程序扮演著遠(yuǎn)程服務(wù)器對象的代理的角色,使該對象可被客戶激活芹橡。 遠(yuǎn)程引用層處理語義毒坛、管理單一或多重對象的通信,決定調(diào)用是應(yīng)發(fā)往一個(gè)服務(wù)器還是多個(gè)林说。傳輸層管理實(shí)際的連接煎殷,并且追蹤可以接受方法調(diào)用的遠(yuǎn)程對象。服務(wù)器端的骨干網(wǎng)完成對服務(wù)器對象實(shí)際的方法調(diào)用腿箩,并獲取返回值蝌数。返回值向下經(jīng)遠(yuǎn)程引用層、服務(wù)器端的傳輸層傳遞回客戶端度秘,再向上經(jīng)傳輸層和遠(yuǎn)程調(diào)用層返回顶伞。最后,占位程序獲得返回值剑梳。
要完成以上步驟需要有以下幾個(gè)步驟: 1唆貌、 生成一個(gè)遠(yuǎn)程接口 2、 實(shí)現(xiàn)遠(yuǎn)程對象(服務(wù)器端程序) 3垢乙、 生成占位程序和骨干網(wǎng)(服務(wù)器端程序) 4锨咙、 編寫服務(wù)器程序 5、 編寫客戶程序 6追逮、 注冊遠(yuǎn)程對象 7酪刀、 啟動(dòng)遠(yuǎn)程對象
STUB和SKELETON
要了解RMI原理.STUB和SKELETON是必須先理解的兩個(gè)概念
做個(gè)比方說明這兩個(gè)概念粹舵。 假如你是A,你想借D的工具骂倘,但是又不認(rèn)識(shí)D的管家C眼滤,所以你找來B來幫你,B認(rèn)識(shí)C历涝。B在這時(shí)就是一個(gè)代理诅需,代理你的請求,依靠自己的話語去借荧库。C呢他負(fù)責(zé)D家東西收回和借出 堰塌,但是要有D的批準(zhǔn)。在得到D的批準(zhǔn)以后分衫,C再把東西給B场刑,B呢再轉(zhuǎn)給A。stub和skeleton在RMI中就是角色就是B和C蚪战,他們都是代理角色摇邦,在現(xiàn)實(shí)開發(fā)中隱藏系統(tǒng)和網(wǎng)絡(luò)的的差異, 這一部分的功能在RMI開發(fā)中對程序員是透明的屎勘。Stub為客戶端編碼遠(yuǎn)程命令并把他們發(fā)送到服務(wù)器。而Skeleton則是把遠(yuǎn)程命令解碼居扒,調(diào)用服務(wù)端的遠(yuǎn)程對象的方法概漱,把結(jié)果在編 碼發(fā)給stub,然后stub再解碼返回調(diào)用結(jié)果給客戶端喜喂。
STUB
Stub為遠(yuǎn)程對象在客戶端的一個(gè)代理瓤摧,當(dāng)客戶端調(diào)用遠(yuǎn)程對象的方法時(shí),實(shí)際是委托Stub這個(gè)代理去調(diào)用遠(yuǎn)程的對象玉吁,這個(gè)調(diào)用過程如下: (1)初始化一個(gè)與遠(yuǎn)程JVM的連接; (2)寫入并傳輸參數(shù)給遠(yuǎn)程JVM; (3)執(zhí)行遠(yuǎn)程對象的方法調(diào)用照弥,并等待調(diào)用結(jié)果的返回(return); (4)讀取調(diào)用的返回值(也可能是一個(gè)異常); (5)返回調(diào)用的結(jié)果給調(diào)用者. 這些操作(序列號(hào)參數(shù), 建立Socket連接等等),都由這個(gè)Stub來透明化进副。
SKELETON
在遠(yuǎn)程的JVM中这揣,每一個(gè)對象(需要被遠(yuǎn)程調(diào)用的對象)都有一個(gè)相應(yīng)的skeleton(在Java2環(huán)境中,這個(gè)skeleton不是必須的)影斑,skeleton的作用是分發(fā)客戶端的調(diào)用到具體的實(shí)現(xiàn)類给赞,skeleton接受 一個(gè)客戶端過來的調(diào)用過程如下: (1)讀取客戶端傳遞過來的參數(shù); (2)調(diào)用實(shí)現(xiàn)類的方法; (3)寫入并傳輸返回結(jié)果給調(diào)用者,同樣的矫户,這個(gè)結(jié)果也是函數(shù)調(diào)用結(jié)果或異常
STUB和SKELETON在什么位置產(chǎn)生
Stub和Skeleton都是在服務(wù)器產(chǎn)生的片迅。Stub存在于客戶端,作為客戶端的代理皆辽,讓我們總是認(rèn)為客戶端產(chǎn)生了stub柑蛇,接口沒有作用芥挣。實(shí)際上stub類是通過Java動(dòng)態(tài)類下載 機(jī)制下載的,它是由服 務(wù)端產(chǎn)生耻台,然后根據(jù)需要?jiǎng)討B(tài)的加載到客戶端空免,如果下次再運(yùn)行這個(gè)客戶端該存根類存在于classpath中,它就不需要再下載了粘我,而是直接加載鼓蜒。總的來說征字,stub是在服務(wù)端產(chǎn)生的都弹,如果服務(wù)端的stub內(nèi)容改變,那么客戶端的也是需要同步更新匙姜。
3.編碼實(shí)戰(zhàn)
4.常見問題
1.多網(wǎng)卡導(dǎo)致的RMI連接問題:
最有效的畅厢,不用改代碼的,就是在服務(wù)器端氮昧,指定server ip. 具體如下: 服務(wù)器程序啟動(dòng)的時(shí)候框杜,java命令加一個(gè)參數(shù):-Djava.rmi.server.hostname=服務(wù)器real ip
2.服務(wù)器重啟之后,客戶端再連接就報(bào)錯(cuò)了袖肥。
RMI客戶客戶端與服務(wù)端第一次建立連接的時(shí)候會(huì)在客戶端生成一個(gè)stub,我們稱之為存根咪辱,并且在服務(wù)端注冊,以后RMI服務(wù)端與客戶端都會(huì)基于這個(gè)文件進(jìn)行通訊椎组,當(dāng)客戶端需要訪問服務(wù)端的時(shí)候會(huì)首先掃描這個(gè)文件油狂,然后訪問客戶端,當(dāng)客戶端驗(yàn)證的時(shí)候發(fā)現(xiàn)注冊了就會(huì)通過寸癌,如果發(fā)現(xiàn)沒有注冊就會(huì)拒絕本次訪問专筷,所以當(dāng)服務(wù)端重啟之后,曾經(jīng)所有stub注冊都會(huì)失效蒸苇,所以客戶端會(huì)一直訪問不到客戶端磷蛹,必須重新啟動(dòng),以獲取新的stub溪烤,不過RMI接口下有避免這種情況的相關(guān)配置.
味咳,配置如下:在客戶端的配置文件中,添加: !-- 連接出錯(cuò)時(shí)自動(dòng)重連 --> property name="refreshStubOnConnectFailure" value="true" /> !-- 不在容器啟動(dòng)的時(shí)候創(chuàng)建與Server端的連接 --> property name="lookupStubOnStartup" value="false" /> 如上配置之后檬嘀,當(dāng)服務(wù)端重啟之后莺葫,客戶端訪問不到服務(wù)端時(shí),會(huì)自動(dòng)去重新獲取stub枪眉,這樣就可以實(shí)現(xiàn)服務(wù)器端重啟之后捺檬,不會(huì)影響到客戶端了,這樣可以給相關(guān)的系統(tǒng)減少很大的風(fēng)險(xiǎn)與麻煩贸铜。
5.參考文獻(xiàn)
https://blog.csdn.net/u011225629/article/details/49861757
https://blog.csdn.net/u014001866/article/details/50936246
http://blog.sina.com.cn/s/blog_492dbb6b0100faot.html
https://blog.csdn.net/smcwwh/article/details/7080997
6.更多討論
鳴謝
感謝觀看,如有出錯(cuò),懇請指正
今天的分享就到這里啦堡纬,歡迎大家點(diǎn)贊聂受、轉(zhuǎn)發(fā)、留言烤镐、拍磚~
????????技能樹.IT修真院
????????“我們相信人人都可以成為一個(gè)工程師蛋济,現(xiàn)在開始,找個(gè)師兄炮叶,帶你入門碗旅,掌控自己學(xué)習(xí)的節(jié)奏,學(xué)習(xí)的路上不再迷镁迪ぃ”祟辟。
????????這里是技能樹.IT修真院,成千上萬的師兄在這里找到了自己的學(xué)習(xí)路線侣肄,學(xué)習(xí)透明化旧困,成長可見化,師兄1對1免費(fèi)指導(dǎo)稼锅『鹁撸快來與我一起學(xué)習(xí)吧~
我的邀請碼:17742750,或者你可以直接點(diǎn)擊此鏈接:http://www.jnshu.com/login/1/17742750
來源:簡書
著作權(quán)歸作者所有矩距。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)拗盒,非商業(yè)轉(zhuǎn)載請注明出處。