代理模式的變體:JAVA RMI(Remote Method Invocation)遠(yuǎn)程代理

今天我們來介紹一下JAVA RMI,大家或許之前從來沒聽說過這個詞蚀浆,但是如果你用過dubbo陈哑、spring cloud等分布式服務(wù)治理框架,理解起來RMI是很輕松的盲赊,因?yàn)樗鼈兊母拍钍遣畈欢嗟南撑簦徊贿^使用的底層協(xié)議不同。

一般情況下哀蘑,在我們本地一個類在調(diào)用另一個類的方法時(shí)诚卸,調(diào)用方與被調(diào)用方都是在同一個堆上的。
如果要從服務(wù)器A調(diào)用服務(wù)器B的方法是辦不到的递礼,因?yàn)樗鼈冊趦蓚€不同的堆上惨险,JVM虛擬機(jī)只能控制自己堆上面的引用地址應(yīng)該如何傳遞的羹幸。

如果想調(diào)用不同的服務(wù)器上面的方法脊髓,要怎么辦?如何設(shè)計(jì)栅受?

下面我們來介紹一下将硝,JAVA RMI是個啥,它是如何實(shí)現(xiàn)不同堆上的調(diào)用屏镊?

JAVA RMI(Remote Method Invocation):大致字面的意思就是執(zhí)行遠(yuǎn)程服務(wù)器方法依疼。

想要利用RMI實(shí)現(xiàn)遠(yuǎn)程調(diào)用,需要創(chuàng)建四個關(guān)鍵對象:

客服端而芥、客戶端輔助對象律罢、服務(wù)端輔助對象、服務(wù)端。

.客戶端:調(diào)用遠(yuǎn)程服務(wù)對象误辑。
.服務(wù)端:帶有客戶端會調(diào)用的方法的對象沧踏。
.客戶端輔助對象(stub):處理客戶端的低層網(wǎng)絡(luò)輸出字節(jié),連接遠(yuǎn)程服務(wù)端巾钉。
.服務(wù)端輔助對象(seleton):處理服務(wù)端的低層網(wǎng)絡(luò)輸入字節(jié)翘狱,連接遠(yuǎn)程客戶端。

輔助對象實(shí)際上就是通信對象砰苍,沒有任何的方法邏輯潦匈。

先簡單描述一下調(diào)用方法的過程:

1.客戶端對象對客戶端輔助對象(stub)調(diào)用dothing()
2.客戶端輔助對象把調(diào)用信息打包(序列化)通過網(wǎng)絡(luò)送到服務(wù)器的服務(wù)端打輔助對象。
3.服務(wù)端輔助對象反序列化得到客戶端輔助對象的信息赚导,并以此調(diào)用真正的服務(wù)茬缩。

如何利用代碼創(chuàng)建遠(yuǎn)程服務(wù)
1.創(chuàng)建Remote接口:

import java.rmi.Remote;
import java.rmi.RemoteException;

/**
 * @Author:zhangyanan
 * @Description: 定義遠(yuǎn)程服務(wù)接口
 * @Date:Crated in 19:22 2020/3/11
 * @Modified By:
 */
public interface MyRemote extends Remote {

    /**
     * 每個遠(yuǎn)程調(diào)用都被認(rèn)為是有風(fēng)險(xiǎn)的,這樣聲明會強(qiáng)迫客戶端注意到這件事
     *
     * @return
     * @throws RemoteException
     */
    String sayHello() throws RemoteException;
}

上面定義接口需要注意的是:
(1)任何遠(yuǎn)程方法的參數(shù)都會被打包通過網(wǎng)絡(luò)傳送,而這是需要序列化完成的辟癌。
(2)如果返回的是自定義類型需要自定義類實(shí)現(xiàn)serialzable接口寒屯。
2.實(shí)現(xiàn)Remote遠(yuǎn)程服務(wù)接口:

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * @Author:zhangyanan
 * @Description: 遠(yuǎn)程服務(wù)端真實(shí)的服務(wù)實(shí)現(xiàn)
 * @Date:Crated in 19:26 2020/3/11
 * @Modified By:
 */
public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {


    protected MyRemoteImpl() throws RemoteException {
    }

    @Override
    public String sayHello() throws RemoteException {
        return null;
    }

    //下面的main函數(shù)是為了向注冊中心注冊服務(wù),以便客戶端可以查找到遠(yuǎn)程服務(wù)并調(diào)用
    public static void main(String[] args) {
        try {
            MyRemote service = new MyRemoteImpl();
            Naming.rebind("Remote Hello",service);
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }
}

(1)實(shí)現(xiàn)MyRemote,就是給客戶端要調(diào)用的方法黍少。
(2)繼承UnicastRemoteObject類寡夹,為了要成為遠(yuǎn)程服務(wù)對象,你的類必須要有與遠(yuǎn)程有關(guān)的功能厂置。其中最簡單的方式就是繼承UnicastRemoteObject菩掏,讓它來處理遠(yuǎn)程連接這些工作。
(3)編寫聲明RemoteException無參構(gòu)造函數(shù):因?yàn)楦割怳nicastRemoteObject構(gòu)造方法定義了異常昵济,所以當(dāng)類初始化的時(shí)候一定會被調(diào)用智绸,如果父類拋出異常,那么子類也要聲明構(gòu)造函數(shù)可能會拋出異常访忿。

3.利用JDK工具rmic產(chǎn)生stub和skeleton:
打開命令窗口瞧栗,對遠(yuǎn)程服務(wù)實(shí)現(xiàn)類執(zhí)行rmic:

rmic MyRemoteImpl

此時(shí)會生成MyRemoteImpl_Stub.class和MyRemoteImpl_skel.class兩個輔助類class,它們是用于連接客戶端和服務(wù)端的海铆。
4.啟動RMI registry(注冊服務(wù)):
打開命令窗口迹恐,執(zhí)行:

rmiregistry

意思是:打開了一個注冊中心,類似于電話號碼本卧斟,用于記錄服務(wù)的地址殴边,方便客戶端查找服務(wù)。
5.啟動遠(yuǎn)程服務(wù):

java MyRemoteImpl

此操作會執(zhí)行MyRemoteImpl類中的mian函數(shù)珍语,使用rebind方法向注冊中心注冊服務(wù)锤岸。

以上就是服務(wù)端要做的事情。
下面我們來說一下客戶端該如何調(diào)用服務(wù):
public class Test {

    public static void main(String[] args) {
        try {
            MyRemote myRemote = (MyRemote) Naming.lookup("rmi://127.0.0.1/Remote Hello");
        } catch (NotBoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

1.客戶端查詢服務(wù):
利用Naming.lookup()方法去registry(注冊中心)尋找要調(diào)用的遠(yuǎn)程服務(wù)板乙,客戶端就像搜電話本一樣是偷,找出上面名稱相符的名稱的服務(wù)。
2.RMI registry返回stub對象,它不是真實(shí)的服務(wù)蛋铆,是真實(shí)服務(wù)的代理饿幅,此對象沒有任何的方法邏輯。它會將調(diào)用的信息傳遞過去(像是方法的名稱和參數(shù)內(nèi)容)戒职,等待服務(wù)器響應(yīng)然后再返回到客戶端栗恩。
3.客戶端就像取用真正的服務(wù)一樣的調(diào)用stub上的方法。
需要注意的是:
(1)客戶端在查詢服務(wù)的時(shí)候必須要有stub類(MyRemoteImpl_Stub.class)洪燥,不然無法在客戶端反序列化磕秤。
(2)服務(wù)端也必須同時(shí)要有stub類和seleton類,它會需要stub類是因?yàn)閟tub會被代換成連接在RMIregistry上真正的服務(wù)捧韵。

上面的只是JDK1.5之前的一些用法市咆,讓大家理解它的作用,1.5以后的版本RMI會結(jié)合動態(tài)代理搭配使用再来,動態(tài)代理產(chǎn)生stub蒙兰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芒篷,隨后出現(xiàn)的幾起案子搜变,更是在濱河造成了極大的恐慌,老刑警劉巖针炉,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件挠他,死亡現(xiàn)場離奇詭異,居然都是意外死亡篡帕,警方通過查閱死者的電腦和手機(jī)殖侵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镰烧,“玉大人拢军,你說我怎么就攤上這事≌睿” “怎么了茉唉?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長败砂。 經(jīng)常有香客問我赌渣,道長魏铅,這世上最難降的妖魔是什么昌犹? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮览芳,結(jié)果婚禮上斜姥,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好铸敏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布缚忧。 她就那樣靜靜地躺著,像睡著了一般杈笔。 火紅的嫁衣襯著肌膚如雪闪水。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天蒙具,我揣著相機(jī)與錄音球榆,去河邊找鬼。 笑死禁筏,一個胖子當(dāng)著我的面吹牛持钉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播篱昔,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼每强,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了州刽?” 一聲冷哼從身側(cè)響起空执,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎穗椅,沒想到半個月后脆烟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡房待,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年邢羔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桑孩。...
    茶點(diǎn)故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡拜鹤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出流椒,到底是詐尸還是另有隱情敏簿,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布宣虾,位于F島的核電站惯裕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏绣硝。R本人自食惡果不足惜蜻势,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鹉胖。 院中可真熱鬧握玛,春花似錦够傍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至拂苹,卻和暖如春安聘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瓢棒。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工搞挣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人音羞。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓囱桨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嗅绰。 傳聞我的和親對象是個殘疾皇子舍肠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容