ZookeeperとRMIテクノロジーを使用して、RPCフレームワークを実装します。
RMIに基づいてリモートメソッド呼び出しを実装します。
1.1 RMIの概要:
Ava自体がRPCフレームワーク(RMI)を提供します(つまり、リモートメソッド呼び出しリモートメソッド呼び出し)。リモート呼び出しとして使用する必要があるインターフェイスを作成する場合は、リモートを継承する必要があります。リモートインターフェイスは、そのメソッドが非ローカル仮想マシンからのものであることを識別するために使用されます。リモートで使用できるのは、「リモートインターフェイス」拡張機能java.rmi.Remoteインターフェイスで指定されたメソッドのみです。
RMIはJava言語のリモート呼び出しであり、言語間で実装することはできません。
1.2実行プロセス
レジストリは、すべてのサーバーオブジェクトが配置される名前名です。サーバーがメソッドを作成するたびに、bind()またはrebind()メソッドを介してレジストリに登録され、一意の名前がバインドされます。
クライアントがサービスのメソッドをリモートで呼び出したい場合は、サーバーにバインドされた名前を使用して、レジストリからオブジェクト(lookup()メソッド)を取得する必要があります。
1.3 RMIAPIの概要
リモートインターフェース
java.rmi.Remoteは、このインターフェイスをリモート呼び出しインターフェイスとして定義します。インターフェイスが外部から呼び出される場合は、このインターフェイスを継承する必要があります
口。
RemoteExceptionクラス
java.rmi.RemoteExceptionは、リモートインターフェイスのインターフェイスを継承します。メソッドをリモートで呼び出すことが許可されている場合は、この例外をスローする必要があります。
UnicastRemoteObjectクラス
java.rmi.server.UnicastRemoteObjectこのクラスは、リモートインターフェイスとSerializableインターフェイスを実装します。
カスタムインターフェイス実装クラスは、カスタムインターフェイスの実装に加えて、このクラスを継承する必要があります。
LocateRegistryクラス
java.rmi.registry.LocateRegistryは、LocateRegistryを介してこのマシンにレジストリを作成でき、特定のポートを介してこのレジストリにアクセスできます。
ネーミングクラス
java.rmi.Namingネーミングは、公開されたコンテンツがアクセスできるRMI名を定義します。指定されたリモートメソッドは、ネーミングによっても取得されます。
1.4サーバーの作成
プロジェクトを作成する
インターフェイスを作成する
リモートインターフェイス、インターフェイスはリモートインターフェイスを継承する必要があり、インターフェイス内のすべてのメソッドはRemoteExceptionをスローする必要があります
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface UserService extends Remote {
String findUsers(String str) throws RemoteException;
}
インターフェイス実装クラスを作成する
リモートインターフェイス実装クラスは、UnicastRemoteObjectを継承する必要があります(RemoteServerの継承-> RemoteObjectの継承-> Remoteの実装、Serializable)。UnicastRemoteObjectクラスを継承することによってのみ、リモートオブジェクトとして使用し、リモートクライアント呼び出しのレジストリに登録できます(補足:クライアントルックアップによって検出されたオブジェクトは、リモートオブジェクトのスタブ(スタブオブジェクト)のみであり、サーバーオブジェクトには対応するスケルトンスケルトン(クライアントスタブ要求を受信して実際のオブジェクトを呼び出すために使用)があります。スタブはリモートオブジェクトです。 Skeletonはリモートオブジェクトのサーバープロキシであり、メソッドが呼び出されると、それらが連携してクライアントとサーバー間の通信を完了します。
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class UserServiceImpl extends UnicastRemoteObject implements UserService {
public UserServiceImpl() throws RemoteException{
}
public String findUsers(String str) throws RemoteException {
return "Hello Zookeeper" + str;
}
}
説明:HelloImplがUnicastRemoteObjectを継承し、リモートオブジェクトとしてリリースできる理由。UnicastRemoteObjectのソースコードを確認して、以下を見つけてください。
/**
* Creates and exports a new UnicastRemoteObject object using an
* anonymous port.
*
* <p>The object is exported with a server socket
* created using the {@link RMISocketFactory} class.
*
* @throws RemoteException if failed to export object
* @since JDK1.1
*/
protected UnicastRemoteObject() throws RemoteException
{
this(0);
}
/**
* Creates and exports a new UnicastRemoteObject object using the
* particular supplied port.
*
* <p>The object is exported with a server socket
* created using the {@link RMISocketFactory} class.
*
* @param port the port number on which the remote object receives calls
* (if <code>port</code> is zero, an anonymous port is chosen)
* @throws RemoteException if failed to export object
* @since 1.2
*/
protected UnicastRemoteObject(int port) throws RemoteException
{
this.port = port;
exportObject((Remote) this, port);
}
/**
* Creates and exports a new UnicastRemoteObject object using the
* particular supplied port and socket factories.
*
* <p>Either socket factory may be {@code null}, in which case
* the corresponding client or server socket creation method of
* {@link RMISocketFactory} is used instead.
*
* @param port the port number on which the remote object receives calls
* (if <code>port</code> is zero, an anonymous port is chosen)
* @param csf the client-side socket factory for making calls to the
* remote object
* @param ssf the server-side socket factory for receiving remote calls
* @throws RemoteException if failed to export object
* @since 1.2
*/
protected UnicastRemoteObject(int port,
RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
throws RemoteException
{
this.port = port;
this.csf = csf;
this.ssf = ssf;
exportObject((Remote) this, port, csf, ssf);
}
実際、サーバー側が起動すると、UserServerImplオブジェクトは新しくなります。UnicastRemoteObjectを継承するため、親クラスの構築メソッドが最初に呼び出されます。このとき、この(現在のオブジェクト)はexportObjectメソッドを介して登録されます。
したがって、エクスポートされたオブジェクトを他のクラスから継承する必要がある場合は、UnicastRemoteObjectを統合する代わりに、exportObjectメソッドを使用してリモートオブジェクトとしてエクスポートできます。
...
// 创建一个远程对象
UserService userService = new UserServiceImpl();
//UserServiceImpl不需要继承UnicastRemoteObject类,通过exportObject将其显示导出
UnicastRemoteObject.exportObject(userService ,0);
...
mainメソッドを書く
サーバー起動クラスは、リモートオブジェクトレジストリを作成し、リモートオブジェクトを登録するために使用されます
import com.hkj.service.UserService;
import com.hkj.service.UserServiceImpl;
import org.apache.zookeeper.*;
import java.io.IOException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class ServiceDemo implements Watcher {
public static void main(String[] args) throws IOException, AlreadyBoundException, KeeperException, InterruptedException {
UserService userService = new UserServiceImpl();
LocateRegistry.createRegistry(8888);
String url = "rmi://localhost:8888/user";
Naming.bind(url,userService);
//将url信息放到zookeeper节点中
ZooKeeper zooKeeper = new ZooKeeper("192.168.1.111:2181,192.168.1.111:2182,192.168.1.111:2183",150000,new ServiceDemo());
//创建Znode
zooKeeper.create("/text/service",url.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println("服务发布成功");
}
public void process(WatchedEvent watchedEvent) {
if (watchedEvent.getState() == Event.KeeperState.SyncConnected){
System.out.println("SUCCESS!");
}
}
}
1.5クライアントレイヤーを作成する
プロジェクトを作成する
サーバーインターフェース
public interface UserService {
String findUser(String str);
}
mainメソッドを書く
import com.hkj.service.UserService;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
public class ClientDemo implements Watcher {
public static void main(String[] args) throws IOException, NotBoundException, KeeperException, InterruptedException {
ZooKeeper zooKeeper = new ZooKeeper("192.168.1.111:2181,192.168.1.111:2182,192.168.1.111:2183",
150000,new ClientDemo());
byte[] bytes = zooKeeper.getData("/test/service",new ClientDemo(),null);
String url = new String(bytes);
UserService userService = (UserService)Naming.lookup(url);
String result = userService.findUser("Nuchkj");
System.out.println(result);
}
public void process(WatchedEvent watchedEvent) {
if(watchedEvent.getState() == Event.KeeperState.SyncConnected);
System.out.println("连接成功");
}
}