Remote Method Invocation 跨虚拟机间调用
使用 RMI 技术可轻松将 服务提供者(Service Provider)与 服务消费者(Service Consumer)进行分离,充分体现组件之间的弱耦合,系统架构更易于扩展
威力 体现在它强大的开发分布式网络应用
通过借助 JNDI命名与目录服务,JNDI 就是一个注册表,服务端将服务对象放入到注册表中,客户端从注册表中获取服务对象。在服务端我们发布了 RMI 服务,并在 JNDI 中进行了注册,此时就在服务端创建了一个 Skeleton(骨架),当客户端第一次成功连接 JNDI 并获取远程服务对象后,立马就在本地创建了一个 Stub(存根),远程通信实际上是通过 Skeleton 与 Stub 来完成的,数据是基于 TCP/IP 协议,在“传输层”上发送的
发布RMI服务
定义一个 RMI 接口
public interface HelloService extends Remote { String sayHello(String name) throws RemoteException;
}
编写 RMI 接口的实现类
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService { protected HelloServiceImpl() throws RemoteException {
} @Override
public String sayHello(String name) throws RemoteException {
return String.format("Hello %s", name);
}
}
通过 JNDI 发布 RMI 服务
public class RmiServer { public static void main(String[] args) throws Exception {
int port = 1099;
String url = "rmi://localhost:1099/demo.zookeeper.rmi.server.HelloServiceImpl";
LocateRegistry.createRegistry(port);
Naming.rebind(url, new HelloServiceImpl());
}
}
调用 RMI 服务
public class RmiClient { public static void main(String[] args) throws Exception {
String url = "rmi://localhost:1099/demo.zookeeper.rmi.server.HelloServiceImpl";
HelloService helloService = (HelloService) Naming.lookup(url);
String result = helloService.sayHello("Jack");
System.out.println(result);
}
}
RPC 和RMI 的区别:
RMI中是通过在客户端的Stub对象作为远程接口进行远程方法的调用。每个远程方法都具有方法签名。如果一个方法在服务器上执行,但是没有相匹配的签名被添加到这个远程接口(stub)上,那么这个新方法就不能被RMI客户方所调用。
RPC中是通过网络服务协议向远程主机发送请求,请求包含了一个参数集和一个文本值,通常形成“classname.methodname(参数集)”的形式。RPC远程主机就去搜索与之相匹配的类和方法,找到后就执行方法并把结果编码,通过网络协议发回。
RMI只用于Java;
RPC是网络服务协议,与操作系统和语言无关。