RPC框架是啥之Java自带RPC实现,RMI框架入门

本博客 猫叔的博客,转载请申明出处

学习系列

Java自带RPC实现,RMI框架入门

首先RMI(Remote Method Invocation)是Java特有的一种RPC实现,它可以使部署在不一样主机上的Java对象进行通讯与方法调用,它是一种基于Java的远程方法调用技术。java

让咱们优先来实现一个RMI的RPC案例吧。git

项目源码地址: RPC_Demo,记得是项目里面的 comgithubrmi
  • 一、首先咱们须要为服务端建立一个接口方法,并且这个接口最好继承Remote
package com.github.rmi.server;

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

/**
 * Create by UncleCatMySelf in 21:03 2019\4\20 0020
 */
public interface MyService extends Remote {

    String say(String someOne)throws RemoteException;

}
  • 二、对于接口实现类,RMI接口方法定义必须显式声明抛出RemoteException异常,服务端方法实现必须继承UnicastRemoteObject类,该类定义了服务调用与服务提供方对象实现,并创建一对一的链接。
package com.github.rmi.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * Create by UncleCatMySelf in 21:05 2019\4\20 0020
 */
public class MyServiceImpl extends UnicastRemoteObject implements MyService {

    protected MyServiceImpl() throws RemoteException {
    }

    public String say(String someOne) throws RemoteException {
        return someOne + ",Welcome to Study!";
    }
}
  • 三、这里咱们还须要一个针对服务端的配置类,由于RMI的通讯端口是随机产生的,所以有可能会被防火墙拦截。为了防止被防火墙拦截,须要强制制定RMI的通讯端口,通常经过自定义一个RMISocketFactory类来实现。
package com.github.rmi.config;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;

/**
 * Create by UncleCatMySelf in 21:15 2019\4\20 0020
 */
public class CustomerSocketFactory extends RMISocketFactory {

    public Socket createSocket(String host, int port) throws IOException {
        return new Socket(host, port);
    }

    public ServerSocket createServerSocket(int port) throws IOException {
        if (port == 0){
            port = 8855;
        }
        System.out.println("RMI 通讯端口 : " + port);
        return new ServerSocket(port);
    }
}
  • 四、好了,这时你能够写出服务端的启动代码了。
package com.github.rmi.server;

import com.github.rmi.config.CustomerSocketFactory;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;

/**
 * Create by UncleCatMySelf in 21:07 2019\4\20 0020
 */
public class ServerMain {

    public static void main(String[] args) throws Exception {
        //注册服务
        LocateRegistry.createRegistry(8866);
        //指定通讯端口,防止被防火墙拦截
        RMISocketFactory.setSocketFactory(new CustomerSocketFactory());
        //建立服务
        MyService myService = new MyServiceImpl();
        Naming.bind("rmi://localhost:8866/myService",myService);
        System.out.println("RMI 服务端启动正常");
    }

}
  • 五、客户端的启动就相对比较简单,咱们仅须要进入服务,并调用对应的远程方法便可。
package com.github.rmi.client;

import com.github.rmi.server.MyService;

import java.rmi.Naming;

/**
 * Create by UncleCatMySelf in 21:10 2019\4\20 0020
 */
public class ClientMain {

    public static void main(String[] args) throws Exception {
        //服务引入
        MyService myService = (MyService) Naming.lookup("rmi://localhost:8866/myService");
        //调用远程方法
        System.out.println("RMI 服务端调用返回:" + myService.say("MySelf"));
    }

}

最后能够看看效果。github

image
image

关于RMI的一些关键点

  • 支持真正的面向对象的多态性,这是RMI的优点。
  • 完美支持Java语言所独有的特性,不支持其余语言。
  • 使用了Java原生序列化,全部序列化对象必须实现java.io.Serializablie接口。
  • 底层通讯是BIO(同步阻塞I/O)实现的Socket
  • 因为BIO与原生序列化存在的性能问题,致使RMI的性能较差,若是你的项目性能要求较高,可能并不合适哦!

公众号:Java猫说

学习交流群:728698035架构

现架构设计(码农)兼创业技术顾问,不羁平庸,热爱开源,杂谈程序人生与不按期干货。

Image Text

相关文章
相关标签/搜索