成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

我要學(xué)好分布式-RMI通信框架

imingyu / 2178人閱讀

摘要:我要學(xué)好分布式通信框架技術(shù)我要學(xué)好分布式分布式框架是最近幾年的熱門。先寫個(gè)測(cè)試用的遠(yuǎn)程接口,注意接口要拋異常實(shí)現(xiàn)遠(yuǎn)程接口,并且繼承創(chuàng)建服務(wù)器程序方法注冊(cè)遠(yuǎn)程對(duì)象創(chuàng)建客戶端程序調(diào)用過程流程去注冊(cè)中心注冊(cè),端啟動(dòng)服務(wù)。

title: 我要學(xué)好分布式-RMI通信框架
date: 2018-07-26 19:28:30

tags: [技術(shù),我要學(xué)好分布式]

分布式框架是最近幾年的熱門??墒且肜斫夥植际娇蚣苤鴮?shí)不易,為了努力跟上時(shí)代潮流,特此開了一個(gè)專題,起名“我要學(xué)好分布式”,通過博客來分享一下我的學(xué)習(xí)過程,加深我對(duì)分布式整體框架的理解。

想要解鎖更多新姿勢(shì)?請(qǐng)?jiān)L問我的博客

什么是RPC

英文就不說了。中文名遠(yuǎn)程進(jìn)程調(diào)用協(xié)議。顧名思義,客戶端在不知道細(xì)節(jié)的情況下,可以調(diào)用遠(yuǎn)程計(jì)算機(jī)的api,就像是調(diào)用本地方法一樣。

RPC協(xié)議是一個(gè)規(guī)范。主流的PRC協(xié)議有Dubbo、Thrif、RMI、WebserviceHessain

他又一個(gè)非常大的特點(diǎn),網(wǎng)絡(luò)協(xié)議和網(wǎng)絡(luò)IO對(duì)于調(diào)用端和服務(wù)端來說是透明的(動(dòng)態(tài)代理)

一個(gè)RPC框架包含的要素:

RMI

RMI(remote method invocation) ?, 可以認(rèn)為是RPC的java版本

RMI使用的是JRMP(Java Remote Messageing Protocol), JRMP是專門為java定制的通信協(xié)議,所以他是純java的分布式解決方案 。注意,這個(gè)RMI已經(jīng)老舊過時(shí)了。

RMI Demo

先寫個(gè)測(cè)試用的遠(yuǎn)程接口,注意接口要拋異常

public interface ISayHello extends Remote {
    public String satHello(String name) throws RemoteException;
}

? 2.實(shí)現(xiàn)遠(yuǎn)程接口,并且繼承:UnicastRemoteObject

public class SayHelloImpl extends UnicastRemoteObject implements ISayHello{

    protected SayHelloImpl() throws RemoteException {
    }

    public String satHello(String name) throws RemoteException {
        return "hello," + name;
    }
}

? 3.創(chuàng)建服務(wù)器程序: createRegistry方法注冊(cè)遠(yuǎn)程對(duì)象

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

public class HelloServer {
    public static void main(String[] args) {
        try {
            ISayHello sayHello =new SayHelloImpl();
            LocateRegistry.createRegistry(8888);
            Naming.bind("rmi://localhost:8888/sayhello",sayHello);
            System.out.println("server start success");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            e.printStackTrace();
        }
    }

? 4.創(chuàng)建客戶端程序

public class HelloClient {
    public static void main(String[] args) {
        try {
            ISayHello iSayHello = (ISayHello) Naming.lookup("rmi://localhost:8888/sayhello");
            System.out.println("hello");
        } catch (NotBoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}
RMI調(diào)用過程

流程:

1.去注冊(cè)中心注冊(cè),server端啟動(dòng)服務(wù)。

2.注冊(cè)中心聯(lián)系stub(存根)。stub用于客戶端 ,在j2ee中是這么說的:為屏蔽客戶調(diào)用遠(yuǎn)程主機(jī)上的對(duì)象,必須提供某種方式來模擬本地對(duì)象,這種本地對(duì)象稱為存根(stub),存根負(fù)責(zé)接收本地方法調(diào)用,并將它們委派給各自的具體實(shí)現(xiàn)對(duì)象

3.server注冊(cè)對(duì)象,然后返回注冊(cè)對(duì)象

4.客戶端訪問注冊(cè)中心,(動(dòng)態(tài)代理)返回stub對(duì)象

5.stub(存根)遠(yuǎn)程調(diào)用skeleton (骨架 )

6.skeleton 調(diào)用相應(yīng)接口

源碼

讓我看看核心的注冊(cè)服務(wù)的源碼實(shí)現(xiàn)

public RegistryImpl(final int var1) throws RemoteException {
        this.bindings = new Hashtable(101);
        //安全認(rèn)證
        if (var1 == 1099 && System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction() {
                    public Void run() throws RemoteException {
                        LiveRef var1x = new LiveRef(RegistryImpl.id, var1);
                        RegistryImpl.this.setup(new UnicastServerRef(var1x, (var0) -> {
                            return RegistryImpl.registryFilter(var0);
                        }));
                        return null;
                    }
                }, (AccessControlContext)null, new SocketPermission("localhost:" + var1, "listen,accept"));
            } catch (PrivilegedActionException var3) {
                throw (RemoteException)var3.getException();
            }
        } else {
            //初始化遠(yuǎn)程引用UnicastServerRef對(duì)象
            LiveRef var2 = new LiveRef(id, var1);//《--------------------------
            this.setup(new UnicastServerRef(var2, RegistryImpl::registryFilter));
        }

    }

點(diǎn)進(jìn)UnicastServerRef,找出實(shí)現(xiàn)的關(guān)系~

點(diǎn)進(jìn)setup方法,用idea反編碼

public Remote exportObject(Remote var1, Object var2, boolean var3) throws RemoteException {
        Class var4 = var1.getClass();

        Remote var5;
        try {
            var5 = Util.createProxy(var4, this.getClientRef(), this.forceStubUse);//《--------------------
        } catch (IllegalArgumentException var7) {
            throw new ExportException("remote object implements illegal remote interface", var7);
        }

        if (var5 instanceof RemoteStub) {//《--------------------------
            this.setSkeleton(var1);
        }

        Target var6 = new Target(var1, this, var5, this.ref.getObjID(), var3);//《------------------------
        this.ref.exportObject(var6);
        this.hashToMethod_Map = (Map)hashToMethod_Maps.get(var4);
        return var5;
    }

發(fā)現(xiàn)在創(chuàng)建代理,判斷當(dāng)前的var是不是遠(yuǎn)程stub,如果是就設(shè)置骨架。如果不是,就構(gòu)建target對(duì)象。點(diǎn)開代理

public static Remote createProxy(Class var0, RemoteRef var1, boolean var2) throws StubNotFoundException {
        Class var3;
        try {
            var3 = getRemoteClass(var0);//《--------------------------
        } catch (ClassNotFoundException var9) {
            throw new StubNotFoundException("object does not implement a remote interface: " + var0.getName());
        }

        if (var2 || !ignoreStubClasses && stubClassExists(var3)) {
            return createStub(var3, var1);//《--------------------------
        } else {
            final ClassLoader var4 = var0.getClassLoader();
            final Class[] var5 = getRemoteInterfaces(var0);
            final RemoteObjectInvocationHandler var6 = new RemoteObjectInvocationHandler(var1);

            try {
                return (Remote)AccessController.doPrivileged(new PrivilegedAction() {
                    public Remote run() {
                        return (Remote)Proxy.newProxyInstance(var4, var5, var6);
                    }
                });
            } catch (IllegalArgumentException var8) {
                throw new StubNotFoundException("unable to create proxy", var8);
            }
        }
    }

發(fā)現(xiàn)在調(diào)用遠(yuǎn)程服務(wù),然后創(chuàng)建了stub。繼續(xù)點(diǎn)開getRemoteClass()方法

 private static Class getRemoteClass(Class var0) throws ClassNotFoundException {
        while(var0 != null) {
            Class[] var1 = var0.getInterfaces();//《--------------------------

            for(int var2 = var1.length - 1; var2 >= 0; --var2) {
                if (Remote.class.isAssignableFrom(var1[var2])) {
                    return var0;
                }
            }

            var0 = var0.getSuperclass();
        }

        throw new ClassNotFoundException("class does not implement java.rmi.Remote");
    }

發(fā)現(xiàn)現(xiàn)在在創(chuàng)建實(shí)例

好吧,回到createProxy方法,再看看順著往下走,看看Target var6 = new Target(var1, this, var5, this.ref.getObjID(), var3);

    `this.ref.exportObject(var6);`的出口對(duì)象方法
public void exportObject(Target var1) throws RemoteException {
        this.ep.exportObject(var1);
    }
public interface Endpoint {
    Channel getChannel();

    void exportObject(Target var1) throws RemoteException;

    Transport getInboundTransport();

    Transport getOutboundTransport();
}
public void exportObject(Target var1) throws RemoteException {
        this.transport.exportObject(var1);
    }

一路點(diǎn)下去,找到了tcp出口的方法。這是屬于協(xié)議層的玩意。

public void exportObject(Target var1) throws RemoteException {
        synchronized(this) {
            this.listen();
            ++this.exportCount;
        }

一路點(diǎn)下去,發(fā)現(xiàn)listen。

private void listen() throws RemoteException {
        assert Thread.holdsLock(this);

        TCPEndpoint var1 = this.getEndpoint();
        int var2 = var1.getPort();
        if (this.server == null) {
            if (tcpLog.isLoggable(Log.BRIEF)) {
                tcpLog.log(Log.BRIEF, "(port " + var2 + ") create server socket");
            }

            try {
                this.server = var1.newServerSocket();//《--------------------------
                Thread var3 = (Thread)AccessController.doPrivileged(new NewThreadAction(new TCPTransport.AcceptLoop(this.server), "TCP Accept-" + var2, true));
                var3.start();
            } catch (BindException var4) {
                throw new ExportException("Port already in use: " + var2, var4);
            } catch (IOException var5) {
                throw new ExportException("Listen failed on port: " + var2, var5);
            }
        } else {
            SecurityManager var6 = System.getSecurityManager();
            if (var6 != null) {
                var6.checkListen(var2);
            }
        }

發(fā)現(xiàn)newServerSocket?。?!

綜上,總體流程和上圖一樣。

RMI缺陷

1.基于java,支持語言單一

2.服務(wù)注冊(cè)只能注冊(cè)到我上面分析的那個(gè)源碼。注冊(cè)中心掛了以后就完了

3.序列化是用java原生那個(gè)方法,效率不好

4.服務(wù)端底層是bio方式,性能不好

手寫RMI

步驟:

編寫服務(wù)器程序,暴露一個(gè)監(jiān)聽, 可以使用socket

編寫客戶端程序,通過ip和端口連接到指定的服務(wù)器,并且將數(shù)據(jù)做封裝(序列化)

服務(wù)器端收到請(qǐng)求,先反序列化。再進(jìn)行業(yè)務(wù)邏輯處理。把返回結(jié)果序列化返回

源碼:https://github.com/tengshe789...

把源碼發(fā)布到GitHub了,在把源碼粘貼太麻煩了。

結(jié)束

此片完了~ 想要了解更多精彩新姿勢(shì)?請(qǐng)?jiān)L問我的個(gè)人博客 .

本篇為原創(chuàng)內(nèi)容,已在個(gè)人博客率先發(fā)表,隨后CSDN,segmentfault,juejin同步發(fā)出。如有雷同,緣分呢兄弟。趕快加個(gè)好友~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76629.html

相關(guān)文章

  • 布式服務(wù)框架之遠(yuǎn)程通訊技術(shù)及原理分析

    摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對(duì)以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...

    sorra 評(píng)論0 收藏0
  • 布式服務(wù)框架之遠(yuǎn)程通訊技術(shù)及原理分析

    摘要:微軟的雖然引入了事件機(jī)制,可以在隊(duì)列收到消息時(shí)觸發(fā)事件,通知訂閱者。由微軟作為主要貢獻(xiàn)者的,則對(duì)以及做了進(jìn)一層包裝,并能夠很好地實(shí)現(xiàn)這一模式。 在分布式服務(wù)框架中,一個(gè)最基礎(chǔ)的問題就是遠(yuǎn)程服務(wù)是怎么通訊的,在Java領(lǐng)域中有很多可實(shí)現(xiàn)遠(yuǎn)程通訊的技術(shù),例如:RMI、MINA、ESB、Burlap、Hessian、SOAP、EJB和JMS等,這些名詞之間到底是些什么關(guān)系呢,它們背后到底是基...

    0xE7A38A 評(píng)論0 收藏0
  • Java 遠(yuǎn)程通訊技術(shù)及原理分析

    摘要:對(duì)于與而言,則可以看做是消息傳遞技術(shù)的一種衍生或封裝。在生產(chǎn)者通知消費(fèi)者時(shí),傳遞的往往是消息或事件,而非生產(chǎn)者自身。通過消息路由,我們可以配置路由規(guī)則指定消息傳遞的路徑,以及指定具體的消費(fèi)者消費(fèi)對(duì)應(yīng)的生產(chǎn)者。采用和來進(jìn)行遠(yuǎn)程對(duì)象的通訊。 消息模式 歸根結(jié)底,企業(yè)應(yīng)用系統(tǒng)就是對(duì)數(shù)據(jù)的處理,而對(duì)于一個(gè)擁有多個(gè)子系統(tǒng)的企業(yè)應(yīng)用系統(tǒng)而言,它的基礎(chǔ)支撐無疑就是對(duì)消息的處理。與對(duì)象不同,消息本質(zhì)上...

    rozbo 評(píng)論0 收藏0
  • 后端必備——數(shù)據(jù)通信知識(shí)(RPC、消息隊(duì)列)一站式總結(jié)

    摘要:具體可以參考消息隊(duì)列之具體可以參考實(shí)戰(zhàn)之快速入門十分鐘入門阿里中間件團(tuán)隊(duì)博客是一個(gè)分布式的可分區(qū)的可復(fù)制的基于發(fā)布訂閱的消息系統(tǒng)主要用于大數(shù)據(jù)領(lǐng)域當(dāng)然在分布式系統(tǒng)中也有應(yīng)用。目前市面上流行的消息隊(duì)列就是阿里借鑒的原理用開發(fā)而得。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問題,目前已經(jīng)開源,會(huì)一直完善下去,歡迎建議和指導(dǎo)歡迎Star: https://github.com/Snail...

    Kahn 評(píng)論0 收藏0
  • 布式下的遠(yuǎn)程通信技術(shù)(RPC)的一些理解

    摘要:都是分開部署,單獨(dú)上線的。序列化畢竟是遠(yuǎn)程通信,需要將對(duì)象轉(zhuǎn)化成二進(jìn)制流進(jìn)行傳輸。服務(wù)化架構(gòu)的演進(jìn)架構(gòu)當(dāng)業(yè)務(wù)規(guī)模很小時(shí),將所有功能都不熟在同一個(gè)進(jìn)程中,通過雙機(jī)或者負(fù)載均衡器實(shí)現(xiàn)負(fù)債分流此時(shí),分離前后臺(tái)邏輯的架構(gòu)是關(guān)鍵。 showImg(https://segmentfault.com/img/bVbiI2F?w=2250&h=1500); 前言 為什么需要RPC,而不是簡(jiǎn)單的HTTP...

    EastWoodYang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<