Zookeeper (三) Zookeeper 实战(RMI)(包含案例源码及解析)

案例源码gitee地址:https://gitee.com/BanSheng/zookeeper-demo/tree/master/rmidemo

 Zookeeper 实战

实战案例介绍:使用 Zookeeper 与 RMI 技术实现一个 RPC 框架。

RPC:RPC(Remote Procedure Call)远程过程调用。

1 基于 RMI 实现远程方法调用

1.1RMI 简 介

RMI(Remote Method Invocation) 远程方法调用。

RMI 是从 JDK1.2 推出的功能,它可以实现在一个 Java 应用中可以像调用本地方法一样

调用另一个服务器中 Java 应用(JVM)中的内容。

RMI 是 Java 语言的远程调用,无法实现跨语言。

1.2执行流程

Registry(注册表)是放置所有服务器对象的命名空间。 每次服务端创建一个对象时,它都会使用 bind()或 rebind()方法注册该对象。 这些是使用称为绑定名称的唯一名称注册的。

要调用远程对象,客户端需要该对象的引用。即通过服务端绑定的名称从注册表中获取对象(lookup()方法)。

1.3RMI 的 API 介绍

1.3.1 Remote 接口

java.rmi.Remote 定义了此接口为远程调用接口。如果接口被外部调用,需要继承此接口。

1.3.2 RemoteException 类

java.rmi.RemoteException

继承了 Remote 接口的接口,如果方法是允许被远程调用的,需要抛出此异常。

1.3.3 UnicastRemoteObject 类

java.rmi.server.UnicastRemoteObject

此类实现了 Remote 接口和 Serializable 接口。

自定义接口实现类除了实现自定义接口还需要继承此类。

1.3.4 LocateRegistry 类

java.rmi.registry.LocateRegistry

可以通过 LocateRegistry 在本机上创建 Registry,通过特定的端口就可以访问这个Registry。

1.3.5 Naming 类

java.rmi.Naming

Naming 定义了发布内容可访问 RMI 名称。也是通过 Naming 获取到指定的远程方法。

1.4创建 Server 端

1.4.1 创建项目

1.4.2 创建接口

/**
* 定义允许远程调用接口,该接口必须要实现 Remote 接口
* 允许被远程调用的方法必须要抛出 RemoteException
*/
public interface DemoService extends Remote {
	String demo(String str) throws RemoteException;
}

1.4.3 创建接口实现类

/**
* 接口实现类必须要继承 UnicastRemoteObject 。
* 会自动添加构造方法,需要修改为 public
*/
public class DemoServiceImpl extends UnicastRemoteObject implements DemoService {
	public DemoServiceImpl() throws RemoteException {
	}
	@Override
	public String demo(String str) throws RemoteException {
		return "Hello RMI "+str;
	}
}

1.4.4 编写主方法

public class DemoServer {
	public static void main(String[] args) throws RemoteException,
	AlreadyBoundException, MalformedURLException {
		// 将对象实例化
		DemoService demoService = new DemoServiceImpl();
		// 创建本地注册表
		LocateRegistry.createRegistry(8888);
		// 将对象绑定到注册表中
		Naming.bind("rmi://localhost:8888/demoService",demoService);
	}
}

1.5创建 Client 端

1.5.1 创建项目

1.5.2 复制服务端接口

/**
* 定义允许远程调用接口,该接口必须要实现 Remote 接口
* 允许被远程调用的方法必须要抛出 RemoteException
*/
public interface DemoService extends Remote {
	String demo(String str) throws RemoteException;
}

1.5.3 创建主方法

public class ClientDemo {
	public static void main(String[] args) throws RemoteException,
	NotBoundException, MalformedURLException {
		DemoService demoService = (DemoService)
		Naming.lookup("rmi://localhost:8888/demoService");
		String result = demoService.demo("bjsxt");
		System.out.println(result);
	}
}

2 使用 Zookeeper 作为注册中心实现 RPC

 

2.1创建服务端

2.1.1 创建项目

2.1.2 修改 POM 文件添加依赖

<dependency>
	<groupId>org.apache.zookeeper</groupId>
	<artifactId>zookeeper</artifactId>
	<version>3.6.0</version>
</dependency>

2.1.3 创建接口

public interface UsersService extends Remote {
	String findUsers(String str) throws RemoteException;
}

2.1.4 创建接口实现类

public interface UsersService extends Remote {
	String findUsers(String str) throws RemoteException;
}
public class UsersServiceImpl extends UnicastRemoteObject implements UsersService {
	public UsersServiceImpl() throws RemoteException {
	}
	@Override
	public String findUsers(String str) throws RemoteException {
		return "Hello Zookeeper "+str;
	}
}

2.1.5 编写主方法

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 的节点中
		ZooKeeper zooKeeper = new ZooKeeper("192.168.233.130:2181,192.168.233.130:2182,192.168.233.
		130:2183",150000,new ServerDemo());
		// 创建 Znode
		zooKeeper.create("/bjsxt/service",url.getBytes(),
		ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
		System.out.println("服务发布成功");
    }
}

2.2创建客户端

2.2.1 创建项目

2.2.2 修改 POM 文件添加依赖

<dependency>
	<groupId>org.apache.zookeeper</groupId>
	<artifactId>zookeeper</artifactId>
	<version>3.6.0</version>
</dependency>

2.2.3 创建接口

public interface UsersService {
	String findUsers(String str);
}

2.2.4 编写主方法

public class ClientDemo implements Watcher {
	public static void main(String[] args) throws IOException,
	KeeperException, InterruptedException, NotBoundException {
		ZooKeeper zooKeeper = new
		ZooKeeper("192.168.233.130:2181,192.168.233.130:2182,192.168.233.130:2183",150000,new ClientDemo());
		byte[] bytes = zooKeeper.getData("/bjsxt/service",new ClientDemo(),null);
		String url = new String(bytes);
		UsersService usersService = (UsersService)
		Naming.lookup(url);
		String result = usersService.findUsers("Bjsxt");
		System.out.println(result);
	}
	@Override
	public void process(WatchedEvent event) {
		if(event.getState() == Event.KeeperState.SyncConnected){
			System.out.println("连接成功");
		}
	}
}

案例源码gitee地址:https://gitee.com/BanSheng/zookeeper-demo/tree/master/rmidemo


版权声明:本文为donglinjob原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。