有没有办法在Hadoop中为Mapper提供构造函数args?可能通过一些包装创造就业的图书馆?
这是我的情景:
public class HadoopTest { // Extractor turns a line into a "feature" public static interface Extractor { public String extract(String s); } // A concrete Extractor, configurable with a constructor parameter public static class PrefixExtractor implements Extractor { private int endIndex; public PrefixExtractor(int endIndex) { this.endIndex = endIndex; } public String extract(String s) { return s.substring(0, this.endIndex); } } public static class Map extends Mapper
应该清楚,因为Mapper只被赋予Configuration
作为类的引用(Map.class
),Hadoop无法传递构造函数参数并配置特定的Extractor.
有一些Hadoop包装框架就像Scoobi,Crunch,Scrunch(可能还有更多我不知道的)似乎有这种能力,但我不知道他们是如何实现的. 编辑:在与Scoobi合作之后,我发现我对此有些不对劲.如果在"映射器"中使用外部定义的对象,则Scoobi要求它是可序列化的,并且如果不是,则会在运行时进行抱怨.所以也许正确的方法就是Extractor
在Mapper的设置方法中使我的序列化和反序列化......
此外,我实际上在Scala工作,所以非常欢迎基于Scala的解决方案(如果不鼓励!)
我建议告诉你的mapper通过Configuration
你正在创建的对象使用哪个提取器.映射器在其setup
方法(context.getConfiguration()
)中接收配置.看起来您不能将对象放在配置中,因为它通常是从XML文件或命令行构造的,但您可以设置枚举值并让映射器自己构造其提取器.在创建映射器之后定制映射器并不是很漂亮,但这就是我对API的解释.
在提交作业时设置实现类名
Configuration conf = new Configuration(); conf.set("PrefixExtractorClass", "com.my.class.ThreePrefixExtractor");
或者使用命令行中的-D选项设置PrefixExtractorClass选项.
下面是mapper中的实现
Extractor extractor = null; protected void setup(Context context) throws IOException, InterruptedException { try { Configuration conf = context.getConfiguration(); String className = conf.get("PrefixExtractorClass"); extractor = Class.forName(className); } Catch (ClassNotFoundException e) { //handle the exception } }
现在使用extractor
map函数中所需的对象.
包含com.my.class.ThreePrefixExtractor
该类的jar 应该分发给所有节点.以下是来自Cloudera 的一篇文章,介绍了不同的方法.
在上面的例子中com.my.class.ThreePrefixExtractor
应该扩展Extractor
类.
使用这种方法可以使映射器实现成为通用的.这是大多数框架采用的方法(使用Class.forName)来实现可实现特定接口的可插入组件.