今天给大家带来一个实战操作,使用java自带的RMI和zookeeper来实现一个RPC框架。通过本文,你可以学习RMI和zookeeper的一些相关知识。
1 JAVA RMI
什么是JAVA RMI呢,我们知道RPC是远程过程调用,而RMI(Remote Method Invocation)远程方法调用,RMI 是从 JDK1.2 推出的功能,它可以实现在一个 Java 应用中可以像调用本地方法一样调用另一个服务器中 Java 应用(JVM)中的内容。听起来是不是很厉害,下面我们先来介绍一下JAVA RMI的实现原理。
2 RMI 执行流程图
我们必须知道关于RMI的几个核心角色和核心方法,如图所示。
2.1 核心角色
RMI的核心角色就是三个,Client,Server,RMI Registry。客户端,服务端,和RMI 注册表。
2.2 核心方法
bind()、rebind()、lookup()。
2.3 执行流程
Registry(注册表)是用来放置所有服务器对象的命名空间。每次服务端创建一个对象之后,它都会使用 bind()或 rebind()方法注册该对象。 这些是使用绑定名称的唯一名称注册的。 要调用远程对象,客户端需要该对象的引用。即通过服务端定的名称从注册表中获取对象(lookup()方法)。
3 RMI API
3.1 Remote 接口
说明:此接口为远程调用接口,如果自定义的接口需要被外部访问,需要实现继承接口。注意是继承,而非实现。
3.2 RemoteException 类
说明:继承了Remote的接口,如果方法是允许被远程调用的,需要抛出此异常。
3.3 UnicastRemoteObject 类
说明:此类实现了Remote和serializable接口,我们自定义的接口实现类除了实现我们写的接口外,还需要继承该类。
3.4 LocateRegistry 类
java.rmi.registry.LocateRegistry:可以通过LocateRegistry在本机上创建Registry,通过特定的端口就可以访问该Registry。
3.5 Naming类
java.rmi.Naming:Naming定义了发布内容可访问RMI名称,通过Naming获取到指定的远程方法。
现在我们已经介绍完了RMI 的相关API,现在我们需要去搭建服务端和客户端,然后通过zookeeper注册中心,就可以实现一个RPC框架。为了方便,我们直接创建一个Maven项目,直接在pom文件加上我们需要zookeeper坐标就好,我这里使用的是3.6.0版本。
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
</dependency>
4 创建服务端
4.1 修改pom文件添加依赖
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
</dependency>
4.2 创建接口 UserService
public interface UsersService extends Remote {
String findUsers(String str) throws RemoteException;
}
4.3 创建接口实现类
public class UsersServiceImpl extends UnicastRemoteObject implements UsersService {
public UsersServiceImpl() throws RemoteException {
}
@Override
public String findUsers(String str) throws RemoteException {
return "Hello Zookeeper "+str;
}
}
4.4 编写服务端主方法
public class ServerDemo implements Watcher {
public static void main(String[] args) throws IOException, AlreadyBoundException, KeeperException, InterruptedException {
UsersService usersService = new UsersServiceImpl();
LocateRegistry.createRegistry(8888);
String url ="rmi://localhost:8888/user";
Naming.bind(url,usersService);
//将url信息放到zookeeper的节点中
// 这里ip就是你zookeeper机器的ip,port默认为2181,看你自己搭建的zookeeper
ZooKeeper zooKeeper = new ZooKeeper("ip:port",150000,new ServerDemo());
//创建Znode,我这里只创建的一个节点,如果你创建了两个节点,必须要保证第一个节点存在,不然会出现异常
zooKeeper.create("/service",url.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("服务发布成功");
}
@Override
public void process(WatchedEvent event) {
if(event.getState() == Event.KeeperState.SyncConnected){
System.out.println("连接成功");
}
}
}
4.5 服务端运行成功截图
如果你运行成功,就会出现如图所示的效果。
5 搭建客户端
5.1 添加项目依赖zookeeper
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.6.0</version>
</dependency>
5.2 创建接口UserService
public interface UsersService {
String findUsers(String str);
}
5.3 编写主客户端
public class ClientDemo implements Watcher {
public static void main(String[] args) throws IOException, KeeperException, InterruptedException, NotBoundException {
ZooKeeper zooKeeper = new ZooKeeper("ip:port",150000,new ClientDemo());
byte[] bytes = zooKeeper.getData("/service",new ClientDemo(),null);
String url = new String(bytes);
UsersService usersService = (UsersService) Naming.lookup(url);
String result = usersService.findUsers("I am Jone");
System.out.println(result);
}
@Override
public void process(WatchedEvent event) {
if(event.getState() == Event.KeeperState.SyncConnected){
System.out.println("连接成功");
}
}
}
5.4 运行成功截图
如图所示,我们就使用zookeeper和Java RMI实现了一个RPC。
6 总结
其实实现起来还是相对比较简单的,本博文省略了搭建zookeeper注册中心部分,但教程网上很多,我这里就不作赘述了。其实也很简单,本博文中的例子也比较简单,后续都会出一些关于RPC的实战操作,有兴趣的可以关注我。