开发分布式的简单应用时,可以考虑使用java的RMI技术,虽然有更加强大的hadoop技术,但是RMI简单易行,可以快速的部署,尤其是在将单机程序转化为分布式程序时,所需的修改很有限。下面是我在一个简易的分布式搜索引擎中所使用的服务器的部署策略以及远程方法调用的实现。 首先介绍开发RMI应用程序的一般步骤: 1.定义服务器对象接口,该接口的作用如同服务器与客户之间的合约,服务器对象接口必须扩展java.rmi.Remote接口 2.定义一个实现服务器对象接口的类,服务器的实现类必须扩展java.rmi.sever.UnicastRemoteObject类,该类对使用TCP流进行点对点的对象引用提供支持 3.用服务器实现类创建一个服务器对象,并把它注册到一个RMI注册处 4.开发一个查找远程对象并调用其方法的客户
分布式意味着所有的机器既是主机,又是客户机。但此处在具体实现时,需要存在一个假定的主机,所有的机器包括他自己都要向他注册。注册以后主机立即通过远程方法调用通知所有的机器并将新加入机器的ip地址写入所有的机器的地址列表中。 分布式搜索引擎的服务器实现的大体框架如下: 初始化方法: (1)创建存储ip地址的xml文件并将自己的ip地址同时作为host地址和client地址 (2)开启RMI注册服务 (3)开启服务器,进行后续的操作 代码如下:
public void init() throws ServletException{
CreateIPxml create=new CreateIPxml();
try {
create.create_xml(); //生成记录本地信息的IP.xml
LocateRegistry.createRegistry(1099); //开启RMI注册服务
new Start_Server();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("初始化完成");
}
在服务器开启(即Start_Server()中)的时候进行注册: (1)获取XML文件中的信息,并设置客户机和服务器的iP地址 (2)服务器的注册
new getIPinfo(); Regist_Server run=new Regist_Server(); run.regist_server();
具体的注册过程 (1)生成提供RMI服务的接口 (2)将提供服务的接口绑定在本地的RMI服务器上 (3)远程方法调用,指定服务器和远程对象的名字 (4)实现新增服务器向主服务器注册,添加IP,注册完成后,ip地址经RMI写入所有机器
CLIENT_SIDE rmi = new CLIENT_SIDE();
Naming.rebind("Ser", rmi);
call=(SERVER_SIDE) Naming.lookup("rmi://" + RemoteIP + "/Ser");
if(call.RegistIP(HostIP))
System.out.println(" 注册成功");
如果主机连接失败(掉线等),则开始选举服务器,具体的选举策略可以根据实际的运行情况来确定,本处直接选取了ip地址最后8位的最大的为主服务器 此处的服务器选举算法值得好好研究
ReadIPlist.go(); //读取当前在线服务器IP Select_MainServer.go(); //选举算法,选举出新主服务器,以便继续运行
远程调用方法的使用: 定义远程接口
public interface SERVER_SIDE extends Remote
{
//作 用:新增服务器向主服务器注册,添加IP
boolean RegistIP(String IP)throws RemoteException ;
//服务器的退出,删除IP
boolean RemoveIP(String IP)throws RemoteException ;
//添加新增服务器的IP,写入IP列表
boolean AddIP(String IP)throws RemoteException;
//在IP列表中删除退出服务器的IP
boolean DelIP(String IP)throws RemoteException;
//获取IP地址列表并返回IP地址列表
ArrayList getIPlist()throws RemoteException ;
//定义搜索方法的远程调用接口,实现分布式搜索
ArrayList remoteserach(String key,String kinds)throws RemoteException ;
ArrayList remotegaojiserach(String key,String type, final String author,final String publisher,final String nokey,final String kind)throws RemoteException ;
ArrayList remoteMp3serach(String key)throws RemoteException ;
ArrayList remoteTupianserach(String key)throws RemoteException ;
ArrayList remotevedioserach(String key)throws RemoteException ;
ArrayList remotewendangserach(String key,String kinds)throws RemoteException ;
//获取远程服务器的目录
String getPath()throws RemoteException ;
}
定义远程接口的实现
public class CLIENT_SIDE extends UnicastRemoteObject implements SERVER_SIDE 略……
为了能够实时的检查到服务器是否因故障掉线,建立Socket通信的服务器端,监听多个客户端状态; 并且建立Socket通信的客户端,向服务器端发送信息,通过这种方式可以检测到机器是否掉线,这项服务在添加主机或者选举完主机以后调用并作为守护进程一直运行。 基于以上的分布式框架可以对将具体的搜索功能部署成分布式的搜索功能,对于其他分布式应用也有借鉴作用。