Hadoop RPC整個使用流程——以DataNode向NameNode註冊爲例 node
在HDFS實現過程當中DataNode class中有一個成員變量namenode,其類型是DatanodeProtocol。namenode能夠看做是遠程NameNode服務器的一個代理,由於NameNode自己也是DatanodeProtocol接口的具體實現;DataNode經過調用namenode對象的方法與遠程NameNode進行交互。 服務器
下面看一下namenode變量在DataNode當中是如何初始化的: socket
首先DataNode經過調用RPC.waiForProxy方法完成namenode的初始化過程,具體實現看下面的代碼: oop
this.namenode = (DatanodeProtocol) RPC.waitForProxy( this
DatanodeProtocol.class, DatanodeProtocol.versionID, debug
nameNodeAddr, 代理
conf); orm
經過上面的代碼能夠看出,具體namenode是如何與遠程的NameNode進行鏈接的須要經過查閱RPC.waitForProxy(...)來查看。waitForProxy經過RPC內部的一系列方法調用,最終經過下面的getProxy方法來實現: server
public static VersionedProtocol getProxy( 對象
Class<? extends VersionedProtocol> protocol,
long clientVersion,
InetSocketAddress addr,
UserGroupInformation ticket,
Configuration conf,
SocketFactory factory,
int rpcTimeout)throws IOException {
if (UserGroupInformation.isSecurityEnabled()) {
SaslRpcServer.init(conf);
}
VersionedProtocol proxy = (VersionedProtocol) Proxy.newProxyInstance(
protocol.getClassLoader(),
new Class[] { protocol },
new Invoker(protocol, addr, ticket, conf, factory, rpcTimeout));
long serverVersion = proxy.getProtocolVersion(protocol.getName(),
clientVersion);
if (serverVersion == clientVersion) {
return proxy;
} else
{
throw new VersionMismatch(protocol.getName(), clientVersion,
serverVersion);
}
}
上面標註爲紅色的代碼是proxy獲取的關鍵(目前對Java Proxy的具體做用不是很瞭解。可是據猜想做用應該是這樣的,Proxy產生了一個protocol的一個具體對象,可是對該對象全部方法的調用都是經過Invoker中的invoke方法來進行調用,也就是其最終的方法調用是經過Invoker的invoke方法進行實現的),其中Invoker是該方法的關鍵,咱們看一下Invoker的具體實現:
Invoker是InvocationHandler接口的具體實現(Invoker implements InvocationHandler),其中必須實現的方法是:
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
final boolean logDebug = LOG.isDebugEnabled();
long startTime = 0;
if (logDebug) {
startTime = System.currentTimeMillis();
}
ObjectWritable value = (ObjectWritable) client.call(new Invocation(
method, args), remoteId);
if (logDebug) {
long callTime = System.currentTimeMillis() - startTime;
LOG.debug("Call: " + method.getName() + " " + callTime);
}
return value.get();
}
invoke方法經過調用client.call方法完成與遠程服務器的調用,client是RPC Client的一個實例。RPC Client具體完成與遠程服務器經過socket進行交互的功能。