好久没有更新Hadoop相关的博客了,实在是各种压力缠身,各种东西都没准备好,面对即将找工作有点没有了节奏。
ok,开始说说今天的主题Hadoop的RPC机制,之所以在HDFS源码解析的系列中添加这部分的内容,是因为DN和NN交互使用的就是RPC的机制,而RPC机制这部分代码年前也是比较深入的研究过,但是是模仿RPC的机制进行分布式检索的实现。
开始先介绍一下RPC几个主要的组成类RPC.java、Client.java、Server.java,其中RPC类主要是提供对外服务的函数实现动态代理机制,Client是RPC进行服务的函数,主要是连接服务器、传递函数名和相应的参数、等待结果返回,Server主要接受Client的请求、执行相应的函数、返回结果。
Hadoop中的RPC比较难理解的部分就是动态代理的实现,下边引用一个其他人博客里的图片(http://blog.csdn.net/tyrone1979/article/details/1232020),感觉这个图画的比较清楚。从图中可以看出动态代理其实只能代理某一个接口,所以所有需要被动态代理的实现类都要实现该接口,在Hadoop中接口是VersionedProtocol。在动态代理中结合了InvocationHandler的功能,保证匿名实现类的方法能够得到正确的执行。使用匿名实现类的对象调用某个方法,实际上调用的是InvocationHandler中的invoke方法,通过该方法将要调用的函数名以及参数告知服务器端,后边会详细介绍一些细节。
结合NN和DN之间的交互作为例子对RPC的原理做一个简单的剖析
在DataNode.java的startDataNode函数中有这样一个调用
348 this.namenode = (DatanodeProtocol)
349 RPC.waitForProxy(DatanodeProtocol.class,
350 DatanodeProtocol.versionID,
351 nameNodeAddr,
352 conf);
我们可以看到通过调用RPC的waitForProxy方法创建了一个DatanodeProtocol对象namenode(其中DatanodeProtocol实现了接口VersionedProtocol),那么namenode应该就是前边提到的匿名实现类的对象,通过这个对象就可以与NN进行交互了。
下边看一下RPC中的相关实现:
首先看一下waitForProxy函数干了些什么
329 while (true) {
330 try {
331 return getProxy(protocol, clientVersion, addr, conf, rpcTimeout);
332 } catch(ConnectException se) { // namenode has not been started
很明显waitForProxy是保证NN出现一些意外的情况下,我们还是可以获得相应的交互对象。那么接着来看getProxy的作用:
392 VersionedProtocol proxy =
393 (VersionedProtocol) Proxy.newProxyInstance(
394 protocol.getClassLoader(), new Class[] { protocol },
395 new Invoker(protocol, addr, tic