【问题标题】:Accessing HDFS HA from spark job (UnknownHostException error)从 spark 作业访问 HDFS HA(UnknownHostException 错误)
【发布时间】:2016-01-15 10:29:36
【问题描述】:

我有 Apache Mesos 0.22.1 集群(3 个主服务器和 5 个从属服务器),在 HA 配置和 Spark 1.5.1 框架中运行 Cloudera HDFS (2.5.0-cdh5.3.1)。

当我尝试 spark-submit 已编译的 HdfsTest.scala 示例应用程序(来自 Spark 1.5.1 源)时 - 它失败并在执行程序日志中出现 java.lang.IllegalArgumentException: java.net.UnknownHostException: hdfs 错误。仅当我将 HDFS HA 路径作为参数 hdfs://hdfs/<file> 传递时才会观察到此错误,当我传递 hdfs://namenode1.hdfs.mesos:50071/tesfile 时 - 一切正常。

我在启用 TRACE 日志记录后发现,Spark 驱动程序实际上正确读取了hdfs://hdfs URL,但 Spark 执行程序 - 没有。

我的 Scala 应用代码:

import org.apache.spark._
object HdfsTest {
  def main(args: Array[String]) {
    val sparkConf = new SparkConf().setAppName("HdfsTest")
    val sc = new SparkContext(sparkConf)
    val file = sc.textFile(args(0))
    val mapped = file.map(s => s.length).cache()
    for (iter <- 1 to 10) {
      val start = System.currentTimeMillis()
      for (x <- mapped) { x + 2 }
      val end = System.currentTimeMillis()
      println("Iteration " + iter + " took " + (end-start) + " ms")
    }
    sc.stop()
   }
  }

我编译这段代码并以集群模式将jar文件提交给Spark:

/opt/spark/bin/spark-submit --deploy-mode cluster --class com.cisco.hdfs.HdfsTest http://1.2.3.4/HdfsTest-0.0.1.jar hdfs://hdfs/testfile

我的 spark-defaults.conf 文件:

spark.master                     spark://1.2.3.4:7077
spark.eventLog.enabled           true
spark.driver.memory              1g

我的 spark-env.sh 文件:

export HADOOP_HOME=/opt/spark
export HADOOP_CONF_DIR=/opt/spark/conf

我在 /opt/spark 目录中的每个从属服务器上部署了 spark。

我可以在控制台中使用“hdfs dfs -ls hdfs://hdfs/”命令访问 HDFS,而无需指定活动名称节点地址和端口。

core-site.xml:
----------------------------------------------------------------------
<configuration>
 <property>
  <name>fs.default.name</name>
  <value>hdfs://hdfs</value>
 </property>
</configuration>

hdfs-site.xml:
----------------------------------------------------------------------
<configuration>
 <property>
  <name>dfs.ha.automatic-failover.enabled</name>
  <value>true</value>
 </property>

 <property>
  <name>dfs.nameservice.id</name>
  <value>hdfs</value>
 </property>

 <property>
  <name>dfs.nameservices</name>
  <value>hdfs</value>
 </property>

 <property>
  <name>dfs.ha.namenodes.hdfs</name>
  <value>nn1,nn2</value>
 </property>

 <property>
  <name>dfs.namenode.rpc-address.hdfs.nn1</name>
  <value>namenode1.hdfs.mesos:50071</value>
 </property>

 <property>
  <name>dfs.namenode.http-address.hdfs.nn1</name>
  <value>namenode1.hdfs.mesos:50070</value>
 </property>

 <property>
  <name>dfs.namenode.rpc-address.hdfs.nn2</name>
  <value>namenode2.hdfs.mesos:50071</value>
 </property>

 <property>
  <name>dfs.namenode.http-address.hdfs.nn2</name>
  <value>namenode2.hdfs.mesos:50070</value>
 </property>

 <property>
  <name>dfs.client.failover.proxy.provider.hdfs</name>
  <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider      </value>
 </property>

 <property>
  <name>dfs.namenode.shared.edits.dir</name>
     <value>qjournal://journalnode1.hdfs.mesos:8485;journalnode2.hdfs.mesos:8485;journalnode3.hdfs.mesos:8485/hdfs</value>
   </property>

 <property>
   <name>ha.zookeeper.quorum</name>
   <value>master.mesos:2181</value>
 </property>

 <property>
  <name>dfs.journalnode.edits.dir</name>
  <value>/var/lib/hdfs/data/jn</value>
 </property>

 <property>
   <name>dfs.namenode.name.dir</name>
   <value>file:///var/lib/hdfs/data/name</value>
 </property>

 <property>
   <name>dfs.datanode.data.dir</name>
   <value>file:///var/lib/hdfs/data/data</value>
 </property>

 <property>
  <name>dfs.ha.fencing.methods</name>
  <value>shell(/bin/true)</value>
 </property>

 <property>
  <name>dfs.permissions</name>
  <value>false</value>
 </property>

 <property>
  <name>dfs.datanode.du.reserved</name>
  <value>10485760</value>
 </property>

 <property>
  <name>dfs.datanode.balance.bandwidthPerSec</name>
  <value>41943040</value>
 </property>

 <property>
   <name>dfs.namenode.safemode.threshold-pct</name>
   <value>0.90</value>
 </property>

 <property>
  <name>dfs.namenode.heartbeat.recheck-interval</name>
  <value>60000</value>
 </property>

 <property>
  <name>dfs.datanode.handler.count</name>
  <value>10</value>
 </property>

 <property>
  <name>dfs.namenode.handler.count</name>
  <value>20</value>
 </property>

 <property>
  <name>dfs.image.compress</name>
  <value>true</value>
 </property>

 <property>
  <name>dfs.image.compression.codec</name>
  <value>org.apache.hadoop.io.compress.SnappyCodec</value>
 </property>

 <property>
  <name>dfs.namenode.invalidate.work.pct.per.iteration</name>
  <value>0.35f</value>
 </property>

 <property>
  <name>dfs.namenode.replication.work.multiplier.per.iteration</name>
  <value>4</value>
 </property>

 <property>
  <name>dfs.namenode.datanode.registration.ip-hostname-check</name>
  <value>false</value>
 </property>

 <property>
   <name>dfs.client.read.shortcircuit</name>
   <value>true</value>
 </property>

 <property>
  <name>dfs.client.read.shortcircuit.streams.cache.size</name>
  <value>1000</value>
 </property>

 <property>
  <name>dfs.client.read.shortcircuit.streams.cache.size.expiry.ms</name>
   <value>1000</value>
 </property>

 <property>
  <name>dfs.domain.socket.path</name>
  <value>/var/run/hadoop-hdfs/dn._PORT</value>
 </property>
</configuration>

【问题讨论】:

    标签: scala apache-spark hdfs mesos mesosphere


    【解决方案1】:

    我找到了解决方案 - 添加

    spark.files file:///opt/spark/conf/hdfs-site.xml,file:///opt/spark/conf/core-site.xml
    

    到每个从站上的conf/spark-defaults.conf 可以解决问题。

    之后,执行程序成功地将core-site.xmlhdfs-site.xml从驱动程序下载到执行程序。

    【讨论】:

    • 太棒了!你能接受这是正确的答案吗?
    • 更正确的解决方案是将spark-env.sh/opt/spark/conf分发给slave
    【解决方案2】:

    Spark 内部将使用可用于 fs.defaultFS 的默认 conf,即您的本地 file://

    为了支持 HDFS HA,您需要通过 CLASSPATH 将 core-site.xmlhdfs-site.xml 传递给 SparkContext,或者如下所示(确保这些文件在本地从节点中的相同位置可用例如:/config/core-site.xml

    例如,Spark 1.x

    val sc = new SparkContext(sparkConf)
    

    火花 2.x

    SparkSession sparkSession = SparkSession.builder().config(sparkConf).getOrCreate();
    val sc = sparkSession.sparkContext()
    

    无论哪种情况,

    sc.hadoopConfiguration().addResource(new org.apache.hadoop.fs.Path("/config/core-site.xml"));
    sc.hadoopConfiguration().addResource(new org.apache.hadoop.fs.Path("/config/hdfs-site.xml"));
    

    【讨论】:

    • 这些文件已经从src/main/resources 中挑选出来。真正允许解析 HA 配置的属性是什么?
    【解决方案3】:

    有必要使用以下方法调用 spark-submit:

    HADOOP_CONF_DIR=/etc/hadoop/conf spark-submit
    

    这可以正确配置 spark。

    【讨论】:

      【解决方案4】:

      从一个非常基本的 IntelliJ 项目(不使用 spark-submit),我验证了这些是您在应用程序的 CLASSPATH 上需要的唯一设置。

      core-site.xml

      <configuration>
          <property>
              <name>fs.defaultFS</name>
              <value>hdfs://hdfscluster</value>
          </property>
      </configuration>
      

      hdfs-site.xml

      <configuration>
          <property>
              <name>dfs.ha.automatic-failover.enabled</name>
              <value>true</value>
          </property>
          <property>
              <name>dfs.client.failover.proxy.provider.hdfscluster</name>
              <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
          </property>
          <property>
              <name>dfs.nameservices</name>
              <value>hdfscluster</value>
          </property>
          <property>
              <name>dfs.ha.namenodes.hdfscluster</name>
              <value>nn1,nn2</value>
          </property>
          <property>
              <name>dfs.namenode.rpc-address.hdfscluster.nn1</name>
              <value>namenode1.fqdn:8020</value>
          </property>
          <property>
              <name>dfs.namenode.rpc-address.hdfscluster.nn2</name>
              <value>namenode2.fqdn:8020</value>
          </property>
      </configuration>
      

      Main.java

      public static void main( String[] args ) {
      
          SparkSession spark = SparkSession.builder()
                  .master("local[*]") // "yarn-client"
                  .getOrCreate();
      
          spark.read().text("hdfs:///tmp/sample.txt");
      }
      

      如果您想通过 YARN 提交,您还需要 yarn-site.xml,但我看到您的问题提到了 Mesos

      【讨论】:

        【解决方案5】:

        java.net.UnknownHostException 表示在这种情况下提供名称为hdfs 的主机无法解析为IP 地址。

        What causes the error - java.net.UnknownHostException

        您可以尝试检查是否解析为 IP 地址ping hdfs

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 2015-01-20
        • 1970-01-01
        • 2018-05-29
        • 2013-03-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多