首页 文章

适用于Hadoop的Hadoop 2.4.1和Google Cloud Storage连接器

提问于
浏览
2

我正在尝试使用Google的Hadoop Cloud 存储连接器在Hadoop上运行Oryx:https://cloud.google.com/hadoop/google-cloud-storage-connector

我更喜欢将Hadoop 2.4.1与Oryx一起使用,所以我使用hadoop2_env.sh设置我在谷歌计算引擎上创建的hadoop集群,例如:

.bdutil -b <BUCKET_NAME> -n 2 --env_var_files hadoop2_env.sh \
--default_fs gs --prefix <PREFIX_NAME> deploy

当我尝试使用hadoop运行oryx时,我面临两个主要问题 .

1)尽管确认我的hadoop conf目录与计算引擎上谷歌安装的预期相符,例如:

$ echo $HADOOP_CONF_DIR
/home/hadoop/hadoop-install/etc/hadoop

我仍然发现正在寻找/ conf目录,例如:

Caused by: java.lang.IllegalStateException: Not a directory: /etc/hadoop/conf

我的理解是../etc/hadoop应该是/ conf目录,例如:hadoop: configuration files

虽然我不需要进行任何更改,但只有在将配置文件复制到新创建的目录中时才会解决此问题,例如:

sudo mkdir /etc/hadoop/conf
sudo cp /home/hadoop/hadoop-install/etc/hadoop/* /etc/hadoop/conf

那么为什么呢?这是使用谷歌hadoop连接器的结果吗?

2)在“解决”上述问题之后,我发现其他错误似乎(对我来说)与hadoop群集和google文件系统之间的通信有关:

Wed Oct 01 20:18:30 UTC 2014 WARNING Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

Wed Oct 01 20:18:30 UTC 2014 INFO Namespace prefix: hdfs://BUCKET_NAME

Wed Oct 01 20:18:30 UTC 2014 SEVERE在com.cloudera.oryx.computation的com.cloudera.oryx.common.servcomp.StoreUtils.listGenerationsForInstance(StoreUtils.java:50)执行java.lang.ExceptionInInitializerError时出现意外错误 . java.util.concurrent.Executors上的PeriodicRunner.run(PeriodicRunner.java:173)java.util的java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)中的$ RunnableAdapter.call(Executors.java:471) .concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.access $ 301(ScheduledThreadPoolExecutor.java:178)java.util.concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1145)java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:615)at java.lang.Thread.run(Thread.java:745)引起:java.lang.IllegalArgumentException:java.net.UnknownHostException :org.apache.hadoop.security.SecurityU的阻力预测在org.apache.hadoop.hdfs.NameNodeProxies.createNonHAProxy(NameNodeProxies.java:258)的org.apache.hadoop.hdfs.NameNodeProxies.createProxy(NameNodeProxies.java:153)中的til.buildTokenService(SecurityUtil.java:373) .apache.hadoop.hdfs.DFSClient . (DFSClient.java:602)org.apache.hadoop.hdfs.DFSClient . (DFSClient.java:547)org.apache.hadoop.hdfs.DistributedFileSystem.initialize(DistributedFileSystem.java) :139)org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2591)org.apache.hadoop.fs.FileSystem.access $ 200(FileSystem.java:89)org.apache.hadoop.fs .FileSystem $ Cache.getInternal(FileSystem.java:2625)org.apache.hadoop.fs.FileSystem $ Cache.get(FileSystem.java:2607)org.apache.hadoop.fs.FileSystem.get(FileSystem.java) :368)com.cloudera.oryx.common.servcomp.Store . (Store.java:76)at com.cloudera.oryx.common.servcomp.Store . (Store.java:57)... 9更多

Caused by: java.net.UnknownHostException: BUCKET_NAME ......还有22个

与我相关的是,当我将默认文件系统设置为gs://时,命名空间前缀为hdfs://

也许这会导致UnkownHostException?

请注意,我已“确认”hadoop群集已连接到google文件系统,例如:hadoop fs -ls会生成我的google Cloud 存储桶的内容以及gs:// BUCKET_NAME目录的所有预期内容 . 但是,我不熟悉hadoop通过hadoop连接器的谷歌表现形式,以及我通常测试看看hadoop群集是否正在运行的传统方式,即:jps仅产生6440 Jps而不是列出所有节点 . 但是,我从hadoop集群的主节点(即PREFIX_NAME-m)运行此命令,并且在使用hadoop的google Cloud 存储连接器时,我不确定预期的输出 .

那么,我如何解决这些错误并让我的oryx作业(通过hadoop)成功访问我的gs:// BUCKET_NAME目录中的数据?

提前感谢您的见解或建议 .

更新:感谢非常详细的回复 . 作为解决方案,我通过更改“硬编码”gs://进入oryx:

prefix = "hdfs://" + host + ':' + port;
} else {
  prefix = "hdfs://" + host;

至:

prefix = "gs://" + host + ':' + port;
} else {
  prefix = "gs://" + host;

我现在得到以下错误:

Tue Oct 14 20:24:50 UTC 2014 SEVERE在com.cloudera.oryx.computation的com.cloudera.oryx.common.servcomp.StoreUtils.listGenerationsForInstance(StoreUtils.java:50)执行java.lang.ExceptionInInitializerError时出现意外错误 . java.util.concurrent.Executors上的PeriodicRunner.run(PeriodicRunner.java:173)java.util的java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)中的$ RunnableAdapter.call(Executors.java:471) .concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.access $ 301(ScheduledThreadPoolExecutor.java:178)java.util.concurrent.ScheduledThreadPoolExecutor $ ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1145)在Java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:615)at java.lang.Thread.run(Thread.java:745)

Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem not found at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1905)org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2573)org.apache.hadoop.fs.FileSystem . creategileSystem(FileSystem.java:2586)位于org.apache.hadoop.fs.FileSystem.access $ 200(FileSystem.java:89)org.apache.hadoop.fs.FileSystem $ Cache.getInternal(FileSystem.java:2625)at at org.apache.hadoop.fs.FileSystem $ Cache.get(FileSystem.java:2607)位于com.cloudera.oryx.common.servcomp的org.apache.hadoop.fs.FileSystem.get(FileSystem.java:368) . Store . (Store.java:76)在com.cloudera.oryx.common.servcomp.Store . (Store.java:57)

根据这里的说明:https://cloud.google.com/hadoop/google-cloud-storage-connector#classpath我相信我已经将连接器jar添加到Hadoop的类路径中;我补充说:

HADOOP_CLASSPATH=$HADOOP_CLASSPATH:'https://storage.googleapis.com/hadoop-lib/gcs/gcs-connector-1.2.9-hadoop2.jar

到/home/rich/hadoop-env-setup.sh . 和(echo $ HADOOP_CLASSPATH)产生:

/contrib/capacity-scheduler/.jar:/home/hadoop/hadoop-install/share/hadoop/common/lib/gcs-connector-1.2.9-hadoop2.jar:/contrib/capacity-scheduler/.jar:/家用/ Hadoop的/ Hadoop的安装/股/的Hadoop / common / lib目录/ GCS-连接器-1.2.9-hadoop2.jar

我是否需要在类路径中添加更多内容?

我还注意到(也许是相关的)即使使用export命令,我仍然会得到/ etc / hadoop / conf的错误 . 我一直在使用sudo mkdir / etc / hadoop / conf作为临时工作 . 我在这里提到它,以防它可能导致其他问题 .

1 回答

  • 1

    似乎有几个问题;第一个通常是,当事情在 hadoop jar 下运行时,hadoop将各种系统环境变量和类路径等嵌入到正在运行的程序中;在你的情况下,因为Oryx运行而不使用 hadoop jar ,而是使用类似的东西:

    java -Dconfig.file=oryx.conf -jar computation/target/oryx-computation-x.y.z.jar
    

    然后 $HADOOP_CONF_DIR 实际上并没有进入环境,所以System.getenv in OryxConfiguration.java无法获取它,并使用默认的 /etc/hadoop/conf 值 . 只需使用 export 命令即可解决此问题,您可以通过查看是否将其置于子shell中进行测试:

    echo $HADOOP_CONF_DIR
    bash -c 'echo $HADOOP_CONF_DIR'
    export HADOOP_CONF_DIR
    bash -c 'echo $HADOOP_CONF_DIR'
    java -Dconfig.file=oryx.conf -jar computation/target/oryx-computation-x.y.z.jar
    

    第二个也是更不幸的问题是Oryx看起来更像是允许用户设置的任何文件系统方案:

    private Namespaces() {
      Config config = ConfigUtils.getDefaultConfig();
      boolean localData;
      if (config.hasPath("model.local")) {
        log.warn("model.local is deprecated; use model.local-data");
        localData = config.getBoolean("model.local");
      } else {
        localData = config.getBoolean("model.local-data");
      }
      if (localData) {
        prefix = "file:";
      } else {
        URI defaultURI = FileSystem.getDefaultUri(OryxConfiguration.get());
        String host = defaultURI.getHost();
        Preconditions.checkNotNull(host,
            "Hadoop FS has no host? Did you intent to set model.local-data=true?");
        int port = defaultURI.getPort();
        if (port > 0) {
          prefix = "hdfs://" + host + ':' + port;
        } else {
          prefix = "hdfs://" + host;
        }
      }
      log.info("Namespace prefix: {}", prefix);
    }
    

    这一切都取决于Oryx是否打算在未来增加对其他文件系统方案的支持,但与此同时,你要么必须自己更改Oryx代码并重新编译,要么你可能试图破解它(但有潜力的碎片)对HDFS有严重依赖的Oryx失败了 .

    理论上,对Oryx的改变应该是:

    String scheme = defaultURI.getScheme();
        if (port > 0) {
          prefix = scheme + "://" + host + ':' + port;
        } else {
          prefix = scheme + "://" + host;
        }
    

    但是,如果你选择了这条路线,请记住eventual list consistency semantics of GCS,其中多阶段工作流程不能依赖于"list"操作来立即查找前一阶段的所有输出;羚羊可能有也可能没有这种依赖性 .

    在您的情况下,最可靠的解决方案是部署 --default_fs hdfs ,其中bdutil仍将安装gcs-connector,以便您可以运行 hadoop distcp 暂时将数据从GCS移动到HDFS,运行Oryx,然后完成后,将其复制回来进入GCS .

相关问题