【问题标题】:Hadoop 2.4.1 and Google Cloud Storage connector for HadoopHadoop 2.4.1 和适用于 Hadoop 的 Google Cloud Storage 连接器
【发布时间】:2015-01-31 18:21:24
【问题描述】:

我正在尝试使用 Google 的 Cloud Storage Connector for Hadoop 在 Hadoop 上运行 Oryx: https://cloud.google.com/hadoop/google-cloud-storage-connector

我更喜欢将 Hadoop 2.4.1 与 Oryx 一起使用,因此我将 hadoop2_env.sh 设置用于我在 google 计算引擎上创建的 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 目录与在计算引擎上安装 google 的预期匹配,例如:

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

我仍然发现 something 正在寻找 /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

那为什么会这样呢?这是使用 google hadoop 连接器的结果吗?

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

2014 年 10 月 1 日星期三 20:18:30 UTC 警告无法为您的平台加载 native-hadoop 库...在适用的情况下使用内置 java 类

2014 年 10 月 1 日星期三 20:18:30 UTC INFO 命名空间前缀:hdfs://BUCKET_NAME

2014 年 10 月 1 日星期三 20:18:30 UTC 严重执行中的意外错误 java.lang.ExceptionInInitializerError 在 com.cloudera.oryx.common.servcomp.StoreUtils.listGenerationsForInstance(StoreUtils.java:50) 在 com.cloudera.oryx.computation.PeriodicRunner.run(PeriodicRunner.java:173) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 在 java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 在 java.lang.Thread.run(Thread.java:745) 引起:java.lang.IllegalArgumentException:java.net.UnknownHostException:电阻预测 在 org.apache.hadoop.security.SecurityUtil.buildTokenService(SecurityUtil.java:373) 在 org.apache.hadoop.hdfs.NameNodeProxies.createNonHAProxy(NameNodeProxies.java:258) 在 org.apache.hadoop.hdfs.NameNodeProxies.createProxy(NameNodeProxies.java:153) 在 org.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) 在 com.cloudera.oryx.common.servcomp.Store.(Store.java:57) ... 9 更多

原因:java.net.UnknownHostException: BUCKET_NAME ... 22 更多

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

也许这会导致 UnkownHostException?

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

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

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

更新: 感谢您非常详细的回复。作为一种解决方法,我通过更改将 gs://“硬编码”到 oryx 中:

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

到:

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

我现在收到以下错误:

2014 年 10 月 14 日星期二 20:24:50 UTC 执行中出现严重的意外错误 java.lang.ExceptionInInitializerError 在 com.cloudera.oryx.common.servcomp.StoreUtils.listGenerationsForInstance(StoreUtils.java:50) 在 com.cloudera.oryx.computation.PeriodicRunner.run(PeriodicRunner.java:173) 在 java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) 在 java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178) 在 java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 在 java.lang.Thread.run(Thread.java:745)

原因:java.lang.RuntimeException:java.lang.ClassNotFoundException:找不到类 com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem 在 org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1905) 在 org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2573) 在 org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2586) 在 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) 在 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:/home/hadoop/hadoop-install/share/hadoop/common/lib/gcs-connector-1.2.9-hadoop2.jar

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

我还注意到(可能相关)即使使用导出命令,我仍然会收到 /etc/hadoop/conf 的错误。我一直在使用 sudo mkdir /etc/hadoop/conf 作为临时解决方法。我在这里提到这一点,以防它可能导致其他问题。

【问题讨论】:

  • 我发现命令“jps”在主节点上作为 hadoop 用户执行时会产生“Jps”、“NameNode”、“ResourceManager”和“SecondaryNameNode”的输出,(hadoop@PREFIX_NAME-米)。但是,当作为 hadoop 用户运行时,oryx/hadoop 作业的输出/错误与从我的默认用户配置文件运行时的输出/错误相同。
  • 当您看到“Caused by: java.lang.IllegalStateException: Not a directory: /etc/hadoop/conf”错误时,您正在运行什么命令?您能否提供该错误背后的其余堆栈跟踪?

标签: hadoop google-compute-engine google-hadoop oryx


【解决方案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 对hard-code 'hdfs' 似乎允许用户设置任何文件系统方案:

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,其中多阶段工作流不得依赖“列表”操作来立即查找前一阶段的所有输出; Oryx 可能有也可能没有这种依赖关系。

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

【讨论】:

    猜你喜欢
    • 2016-02-06
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    相关资源
    最近更新 更多