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

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

我正在尝试使用Google的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

我仍然发现某些内容正在寻找/ 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警告无法使用适用于的内置Java类为平台加载本机Hadoop库...

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

2014年10月1日星期三20:18:30 UTC SEVERE执行中发生意外错误
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://时, namespace 前缀为hdfs://

也许这导致了UnkownHostException?

请注意,我已“确认” hadoop群集已连接到google文件系统,例如:
hadoop fs -ls
产生我的Google云存储桶的内容以及gs:// BUCKET_NAME目录的所有预期内容。但是,我不熟悉通过hadoop连接器在hadoop上的google表现形式,以及我通常测试以查看hadoop集群是否正在运行的传统方式,即:
jps
只有产量
6440 Jps
而不是列出所有节点。但是,我是从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 SEVERE执行中发生意外错误
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:/主页/ hadoop / hadoop安装/共享/hadoop/common/lib/gcs-connector-1.2.9-hadoop2.jar

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

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

最佳答案

似乎有几个问题。首先,通常,当事物在hadoop jar下运行时,hadoop将各种系统环境变量和类路径等注入(inject)正在运行的程序中;在您的情况下,由于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,在该处,多阶段工作流一定不能依靠“列表”操作来立即找到上一阶段的所有输出。羚羊可能有也可能没有这种依赖性。

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

关于hadoop - Hadoop 2.4.1和适用于Hadoop的Google Cloud Storage连接器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26150155/

相关文章:

hadoop - HDFS 在存储数据时是否加密或压缩数据?

scala - 将Spark插入Java堆空间

scala - 不止一个 Spark 上下文错误

google-compute-engine - 谷歌计算引擎工具gcloud异常慢

elasticsearch - 在 Google Compute Engine 上使用抢占式虚拟机

hadoop - Spark 作业似乎不能很好地并行化

hadoop - 从 Hadoop 访问只读的 Google Storage 存储桶

r - R-install.packages在计算引擎上的Coreos上的Docker中不起作用

hadoop - 适用于 Hadoop 的 Google Cloud 连接器不适用于 Pig

hadoop - Spark/Hadoop/Yarn集群通信需要外部ip?