hadoop中的RPC, namenode和datanode通信原理

1. JobClient(题外话,自己翻译了一下JobClient的运行机制):
JobClient是用户提交的信息与JobTracker交互的主要接口。它提供的功能有:提交作业,跟踪作业进度,访问作业报告和进度,获取MR集群的状态等。
作业提交过程:
a. 检查作业的输入输出是否合乎规范;
b. 为作业计算出InputSplit(单个Mapper需要执行的部分);
c. 如有需要,为DistributedCache设置一些必要的统计信息;
d. 将作业的jar文件和配置文件copy到分布式系统的目录中;
e. 提交作业给JobTracker, 并且有选择地或者说随意地侦听其作业状态。
通常来说用户创建应用程序,通过JobConf设定一些配置参数,然后使用JobClient来提交作业,并且监视作业进度:
下面例子说明怎样使用JobClient:
*     // 创建新的JobConf对象
*     JobConf job = new JobConf(new Configuration(), MyJob.class);
*     
*     // 指定一些配置参数    
*     job.setJobName("myjob");
*     
*     job.setInputPath(new Path("in"));
*     job.setOutputPath(new Path("out"));
*     
*     job.setMapperClass(MyJob.MyMapper.class);
*     job.setReducerClass(MyJob.MyReducer.class);
*
*     // 提交作业,然后一直监视作业进度,直到其完成
*     JobClient.runJob(job);
作业控制

有时候客户端需要使用责任链模式来完成一些复杂的job,这是相当容易实现的。因为前一个job输出到分布式文件系统的结果能够成为下一个job的输入。然而,这些作业能够成功完成完全依赖于这些client的正确控制。在这样的情境下,作业控制选择有:
runJob: 只有在前面的作业完成后才提交作业;
submitJob: 提交作业,然后监视正在运行的作业进度,进行作业调度决策;
setJobEndNotificationURI:设置一个作业完成的提示,并停止监听。
2. JobTracker
它是网络环境中实现提交和跟踪作业的核心。我们可以从它实现的接口中,猜测它的功能:
MRConstants 一些默认参数的定义,比如mapred.disk.healthChecker.interval,检查磁盘间隔
InterTrackerProtocol 与TaskTracker进行交互,如发送心跳、报告错误等
JobSubmissionProtocol   与JobClient进行交互,如提交作业、管理作业以及任务
TaskTrackerManager 管理集群上的TaskTrackers,这个接口主要是为了测试JobTracker,不建议用户继承使用
RefreshUserMappingsProtocol  安全相关的协议,JobTracker和NameNode都实现了它
RefreshAuthorizationPolicyProtocol 更新当前使用的服务层的认证策略
AdminOperationsProtocol 管理操作,服务于框架,不建议用户使用
    JobTrackerMXBean JobTracker自身的一些信息
3. RPC实现机制
有关VersionedProtocol的基本都是基于RPC实现,我们下面来分析一下JobSubmissionProtocol,其他同理。
JobSubmissionProtocol是JobTracker和JobClient用来交流的协议, JobTracker实现了这个接口中的所有方法。JobClient通过这个接口来调用JobTracker中的方法来提交作业,使其运行并监控作业状态。
在JobTracker的构造方法:JobTracker(final JobConf conf, String identifier, Clock clock, QueueManager qm) 中可以找到下面的代码:
this.interTrackerServer = RPC.getServer(this, addr.getHostName(), addr.getPort(), handlerCount, 
          false, conf, secretManager);
  也就是JobTracker作为RPC协议中的Server,那么聪明的你已经想到JobClient肯定也会监听这个接口,通过RPC,使用本地代理调用Server端的接口。好的,那么我们去找JobClient端的相应代码,Server和Client连接的接口JobSubmissionProtocol是个很好的线索:
  JobSubmissionProtocol rpcJobSubmitClient = 
        (JobSubmissionProtocol)RPC.getProxy(
            JobSubmissionProtocol.class,
            JobSubmissionProtocol.versionID, addr, 
            UserGroupInformation.getCurrentUser(), conf,
            NetUtils.getSocketFactory(conf, JobSubmissionProtocol.class), 
            0,
            RetryUtils.getMultipleLinearRandomRetry(
                conf,
                MAPREDUCE_CLIENT_RETRY_POLICY_ENABLED_KEY,
                MAPREDUCE_CLIENT_RETRY_POLICY_ENABLED_DEFAULT,
                MAPREDUCE_CLIENT_RETRY_POLICY_SPEC_KEY,
                MAPREDUCE_CLIENT_RETRY_POLICY_SPEC_DEFAULT
                )
            );
    果然不出所料,通过如上的代码,在Client端建立Server的proxy对象,那么就可以进行使用了。方法的实现是在Server端的。

4. 下面贴出自己的模拟实现代码,多多指教!

NameNoder

package rpc;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Server;

public class NameNoder implements TestProtocol{

	/**
     * @param instance the instance whose methods will be called
     * @param conf the configuration to use
     * @param bindAddress the address to bind on to listen for connection
     * @param port the port to listen for connections on
     * @param numHandlers the number of method handler threads to run
     * @param verbose whether each call should be logged
     */
	public static String ADDRESS = "hdfs://will-vm1";
	public static int PORT = 9000;
	/**
	 * shift + alt + L 快速生成变量
	 * shife + alt + M 抽取方法
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		Server server = RPC.getServer(new NameNoder(), ADDRESS, PORT, new Configuration());
		server.start();
	}
	
	@Override
	public long getProtocolVersion(String protocol, long clientVersion)
			throws IOException {
		return TestProtocol.version;
	}
	
	@Override
	public String clientMethod(String str) {
		return "(In server) This is clientMethod --- " + str;
	}

}
DataNoder

package rpc;

import java.io.IOException;
import java.net.InetSocketAddress;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.VersionedProtocol;

public class DataNoder {
	
	/** Construct a client-side proxy object that implements the named protocol,
	   * talking to a server at the named address.
	   * 构造一个实现客户端的代理对象,这个代理对象实现了protocol 
	 * @throws IOException */
	public static void main(String[] args) throws IOException {
		TestProtocol proxy = (TestProtocol) RPC.waitForProxy(TestProtocol.class,
				  TestProtocol.version,
			      new InetSocketAddress(NameNoder.ADDRESS, NameNoder.PORT),
			      new Configuration());
		final String result = proxy.clientMethod("test");
		System.err.println(result);
		
		RPC.stopProxy(proxy);
	}

}
TestProtocol

package rpc;

import org.apache.hadoop.ipc.VersionedProtocol;

public interface TestProtocol extends VersionedProtocol{
	public static long version = 234324324;
	public String clientMethod (String str);
}

敬请指教! Any sugesstions will be appreciated!

你可能感兴趣的:(hadoop)