考虑一个正在运行的作业,其中自定义 InputFormat 需要从其覆盖的方法Hadoop
中与驱动程序类(即,与启动作业的类)通信(“返回”,类似于回调)一些简单的值,getSplits()
使用新的mapreduce
API(而不是mapred
)。
理想情况下,这些值应该在内存中返回(而不是将它们保存到HDFS
或DistributedCache
)。
如果这些值只是数字,人们可能会想使用Hadoop
计数器。然而,在许多测试中,计数器似乎在该getSplits()
阶段不可用,并且无论如何它们仅限于数字。
另一种方法是使用Configuration
作业的对象,正如源代码所揭示的那样,它应该是内存中的同一个对象。getSplits()
对于驱动程序类和驱动程序类,它应该是内存中的同一个对象。
在这种情况下,如果InputFormat
想要向驱动程序类“返回”一个(比如说)正长值,代码将如下所示:
// In the custom InputFormat.
public List<InputSplit> getSplits(JobContext job) throws IOException
{
...
long value = ... // A value >= 0
job.getConfiguration().setLong("value", value);
...
}
// In the Hadoop driver class.
Job job = ... // Get the job to be launched
...
job.submit(); // Start running the job
...
while (!job.isComplete())
{
...
if (job.getConfiguration().getLong("value", -1))
{
...
}
else
{
continue; // Wait for the value to be set by getSplits()
}
...
}
以上在测试中有效,但它是一种“安全”的价值交流方式吗?
或者对于这种内存中的“回调”有更好的方法吗?
更新
“内存回调”技术可能不适用于所有Hadoop
发行版,因此,如上所述,一种更安全的方法是,与其保存要在Configuration
对象中传回的值,不如创建一个自定义对象,将其序列化(例如,作为JSON),将其保存(在 HDFS 或分布式缓存中)并在驱动程序类中读取。我也测试了这种方法,它按预期工作。