作爲典型的分佈式系統,Hadoop中各個實體間存在着大量的交互,遠程過程調用讓用戶可以像調用本地方法一樣調用另外一個應用程序提供的服務,而不必設計和開發相關的信息發送、處理和接收等具體代碼,是一種重要的分佈式計算技術,它提高了程序的互操作性,在Hadoop的實現中得到廣泛的應用。
Hadoop沒有使用Java RMI,而是實現了一套自己獨有的節點間通信機制,理由是有效的IPC(Inter-Process Communication,進程間通信)對於Hadoop來說是至關重要的,Hadoop需要精確控制進程間通信中比如連接、超時、緩存等通信細節。
如下是Hadoop 框架中實現了客戶端調用JobTracker服務器端方法的一個具體應用,功能是返回分配給新作業的ID串。接下來從客戶端調用、服務器端接口及功能實現和服務器端的監聽來展現這一功能。
1 客戶端調用類JobClient
publicclass JobClient extends Configured implements MRConstants, Tool {
private JobSubmissionProtocol jobSubmitClient;
// 客戶端通過代理對象直接進行方法調用。
public RunningJob submitJobInternal(final JobConf job) {
... ...
JobID jobId = jobSubmitClient.getNewJobId();
... ...
}
// 如下是代理對象的構造方法,首先判斷當前hadoop環境是否是本地的,如果不是本地的則構造一個要請求服務器的網絡地址(IP和端口),網絡地址的信息來自於配置文件中屬性mapred.job.tracker的配置,如果配置文件沒有該項配置,則取默認值local。
publicvoid init(JobConf conf) throws IOException {
String tracker = conf.get("mapred.job.tracker", "local");
if ("local".equals(tracker)) {
conf.setNumMapTasks(1);
this.jobSubmitClient = new LocalJobRunner(conf);
} else {
this.jobSubmitClient = createRPCProxy(JobTracker.getAddress(conf), conf);
}
}
在IPC中,使用RPC.getProxy()方法獲取到一個JobSubmissionProtocol代理對象。
privatestatic JobSubmissionProtocol createRPCProxy(InetSocketAddress addr,Configuration conf) throws IOException {
return (JobSubmissionProtocol) RPC.getProxy(JobSubmissionProtocol.class,
JobSubmissionProtocol.versionID, addr,
UserGroupInformation.getCurrentUser(), conf,
NetUtils.getSocketFactory(conf, JobSubmissionProtocol.class));
}
2 接口JobSubmissionProtocol
如下是服務器端服務接口定義:
interface JobSubmissionProtocol extends VersionedProtocol {
publicstaticfinallongversionID = 28L;
/**
* Allocate a name for the job.
* @return a unique job name for submitting jobs.
* @throws IOException
*/
public JobID getNewJobId() throws IOException;
}
3 實現類JobTracker
如下是服務器端服務實現類定義:
publicclass JobTracker implements MRConstants, InterTrackerProtocol,
JobSubmissionProtocol, TaskTrackerManager, RefreshUserMappingsProtocol,
RefreshAuthorizationPolicyProtocol, AdminOperationsProtocol,
JobTrackerMXBean {
/**
* Allocates a new JobId string.
*/
publicsynchronized JobID getNewJobId() throws IOException {
returnnew JobID(getTrackerIdentifier(), nextJobId++);
}
}
4 服務器監聽類
在服務器端先構造一個要提供服務的網絡地址addr,傳遞到RPC.getServer()方法中。服務器端使用RPC.getServer()方法創建服務器端對象interTrackerServer。
Server端的Handler實例(線程)的個數爲由配置文件的屬性mapred.job.tracker.handler.count指定。
publicclass JobTracker implements MRConstants, InterTrackerProtocol,
JobSubmissionProtocol, TaskTrackerManager, RefreshUserMappingsProtocol,
RefreshAuthorizationPolicyProtocol, AdminOperationsProtocol,
JobTrackerMXBean {
JobTracker(final JobConf conf, String identifier, Clock clock, QueueManagerqm) {
... ...
InetSocketAddress addr = getAddress(conf);
... ...
inthandlerCount = conf.getInt("mapred.job.tracker.handler.count", 10);
this.interTrackerServer =
RPC.getServer(this, addr.getHostName(), addr.getPort(), handlerCount,
false, conf, secretManager);
... ...
}
publicstatic InetSocketAddress getAddress(Configuration conf) {
String jobTrackerStr =
conf.get("mapred.job.tracker", "localhost:8012");
return NetUtils.createSocketAddr(jobTrackerStr);
}
}