RPC是远程过程调用(Remote Procedure Call),即远程调用其他虚拟机中运行的java object。RPC是一种客户端/服务器模式,那么在使用时包括服务端代码和客户端代码,还有我们调用的远程过程对象。
HDFS的运行就是建立在此基础之上的。本章通过分析实现一个简单的RPC程序来分析HDFS的运行机理。
下面的代码是服务端代码。
public class MyServer { public static final int SERVER_PORT = 12345; public static final String SERVER_ADDRESS = "localhost"; public static void main(String[] args) throws IOException { final Server server = RPC.getServer(new MyBiz(), SERVER_ADDRESS, SERVER_PORT, new Configuration()); server.start(); } }
核心在于第5行的RPC.getServer方法,该方法有四个参数,第一个参数是被调用的java对象,第二个参数是服务器的地址,第三个参数是服务器的端口 。获得服务器对象后,启动服务器。这样,服务器就在指定端口监听客户端的请求。
下面的代码是被调用的远程对象类。
public class MyBiz implements MyBizable{ public static long BIZ_VERSION = 2345234L; @Override public String hello(String name){ System.out.println("我被调用了"); return "hello "+name; } @Override public long getProtocolVersion(String protocol, long clientVersion) throws IOException { return BIZ_VERSION; } }
被调用的远程对象实现了接口MyBizable,这里面有两个方法被实现,一个就是hello方法,另一个是getProtocalVersion方法。这个hello方法内部有个输出语句。
下面的代码是远程调用类的接口定义。
public interface MyBizable extends VersionedProtocol{ public abstract String hello(String name); }
这个接口中的方法就是刚才的Biz中实现的方法。接口继承的VersionedProtocal,是hadoop的RPC的接口,所有的RPC通信 必须实现这个一接口,用于保证客户端和服务端的端口一致。服务端被调用的类必须继承这个接口VersionedProtocal。
下面是客户端代码,这里使用的调用对象的接口。
public class MyClient { public static void main(String[] args) throws Exception { final MyBizable proxy = (MyBizable)RPC.getProxy(MyBizable.class, MyBiz.BIZ_VERSION, new InetSocketAddress(MyServer.SERVER_ADDRESS, MyServer.SERVER_PORT), new Configuration()); //调用接口中的方法 final String result = proxy.hello("world"); System.out.println(result); //本质是关闭网络连接 RPC.stopProxy(proxy); } }
以上代码中核心在于RPC.getProxy(),该方法有四个参数,第一个参数是被调用的接口类,第二个是客户端版本号,第三个是服务端地址。返回的代理对象,就是服务端对象的代理,内部就是使用java.lang.Proxy实现的。
运行时,先启动服务端,再启动客户端。读者可以服务端和客户端输出信息。
从上面的RPC调用中,可以看出:在客户端调用的业务类的方法是定义在业务类的接口中的。该接口实现了VersionedProtocal接口。
现在我们在命令行执行jps命令,查看输出信息,如图5-1所示。
图5-1
可以看到一个java进程,是“MyServer”,该进程正是我们刚刚运行的rpc的服务端类MyServer。大家可以联想到我们搭建 hadoop环境时,也执行过该命令用来判断hadoop的进程是否全部启动。那么可以判断,hadoop启动时产生的5个java进程也应该是RPC的 服务端。我们观察NameNode的源代码,如图5-2,可以看到NameNode确实创建了RPC的服务端。
图5-2