天天看點

spark 2.x在windows環境使用idea本地調試啟動了kerberos認證的hive

spark 2.x在windows環境使用idea本地調試啟動了kerberos認證的hive

1 概述

開發調試spark程式時,因為要通路開啟kerberos認證的hive/hbase/hdfs等元件,每次調試都需要打jar包,上傳到伺服器執行特别影響工作效率,是以調研了下如何在windows環境用idea直接跑spark任務的方法,本文旨在記錄配置本地調試環境中遇到的問題及解決方案。

2 環境

Jdk 1.8.0

Spark 2.1.0

Scala 2.11.8

Hadoop 2.6.0-cdh5.12.1

Hive 1.1.0-cdh5.12.1

環境搭建略,直接看本地調試spark程式遇到的問題。

注意:若要通路遠端hadoop叢集服務,需将hosts配置到windows本地。

3 測試代碼

測試主類,功能spark sql讀取開啟Kerberos認證的遠端hive資料

import org.apache.spark.sql.SparkSession

object SparkTest{
  def main(args: Array[String]): Unit = {
    //kerberos認證
    initKerberos()

    val spark = SparkSession.builder().master("local[2]").appName("SparkTest")
    .enableHiveSupport()
    .getOrCreate()
    spark.sql("show databases").show()
    spark.sql("use testdb")
    spark.sql("show tables").show()

    val sql = "select * from infodata.sq_dim_balance where dt=20180625 limit 10"
    spark.sql(sql).show()

    spark.stop()
  }

def initKerberos(): Unit ={
  //kerberos權限認證
  val path = RiskControlUtil.getClass.getClassLoader.getResource("").getPath
  val principal = PropertiesUtil.getProperty("kerberos.principal")
  val keytab = PropertiesUtil.getProperty("kerberos.keytab")

  val conf = new Configuration
  System.setProperty("java.security.krb5.conf", path + "krb5.conf")
  conf.addResource(new Path(path + "hbase-site.xml"))
  conf.addResource(new Path(path + "hdfs-site.xml"))
  conf.addResource(new Path(path + "hive-site.xml"))
  conf.set("hadoop.security.authentication", "Kerberos")
  conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem")
  UserGroupInformation.setConfiguration(conf)
  UserGroupInformation.loginUserFromKeytab(principal, path + keytab)
  println("login user: "+UserGroupInformation.getLoginUser())
}
}           

4 問題及解決方案

4.1 問題1

java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.           

winutils.exe是在Windows系統上需要的hadoop調試環境工具,裡面包含一些在Windows系統下調試hadoop、spark所需要的基本的工具類

出現上面的問題,可能是因為windows環境下缺少winutils.exe檔案或者版本不相容的原因。

解決辦法:

(1)下載下傳winutils,注意需要與hadoop的版本相對應。

hadoop2.6版本可以在這裡下載下傳https://github.com/amihalik/hadoop-common-2.6.0-bin

由于配置的測試叢集是hadoop2.6,是以我在這裡下載下傳的是2.6.0版本的。下載下傳後,将其解壓,包括:hadoop.dll和winutils.exe

(2)配置環境變量

①增加系統變量HADOOP_HOME,值是下載下傳的zip包解壓的目錄,我這裡解壓後将其重命名為hadoop-common-2.6.0

②在系統變量path裡增加%HADOOP_HOME%\bin

③重新開機電腦,使環境變量配置生效,上述問題即可解決。  

添加系統變量HADOOP_HOME

spark 2.x在windows環境使用idea本地調試啟動了kerberos認證的hive

編輯系統變量Path,添加%HADOOP_HOME%\bin;

spark 2.x在windows環境使用idea本地調試啟動了kerberos認證的hive

4.2 問題2

如果hadoop叢集開啟了kerberos認證,本地調試也需要進行認證,否則會報權限錯誤;

将權限相關配置檔案放入工程的resource目錄,如下所示

spark 2.x在windows環境使用idea本地調試啟動了kerberos認證的hive

認證代碼如下:

def initKerberos(): Unit ={
  //kerberos權限認證
  val path = RiskControlUtil.getClass.getClassLoader.getResource("").getPath
  val principal = PropertiesUtil.getProperty("kerberos.principal")
  val keytab = PropertiesUtil.getProperty("kerberos.keytab")

  val conf = new Configuration
  System.setProperty("java.security.krb5.conf", path + "krb5.conf")
  conf.addResource(new Path(path + "hbase-site.xml"))
conf.addResource(new Path(path + "hdfs-site.xml"))
conf.addResource(new Path(path + "hive-site.xml"))
  conf.set("hadoop.security.authentication", "Kerberos")
  conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem")
  UserGroupInformation.setConfiguration(conf)
  UserGroupInformation.loginUserFromKeytab(principal, path + keytab)
  println("login user: "+UserGroupInformation.getLoginUser())
}           

4.3 問題3

Caused by: java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.createDirectoryWithMode0(Ljava/lang/String;I)V           

網上說目前錯誤的解決辦法還沒有解決,采用一種臨時的方式來解決,解決的辦法是:通過下載下傳你的CDH的版本的源碼(http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.12.1-src.tar.gz),

在對應的檔案下,hadoop2.6.0-cdh5.12.1-src\hadoop-common-project\hadoop- common\src\main\java\org\apache\hadoop\io\nativeio下NativeIO.java 複制到對應的Eclipse的project(複制的過程中需要注意一點,就是在目前的工程下建立相同的包路徑,這裡的包路徑org.apache.hadoop.io.nativeio再将對應NativeIO.java檔案複制到對應的包路徑下即可。)

Windows的唯一方法用于檢查目前程序的請求,在給定的路徑的通路權限,是以我們先給以能進行通路,我們自己先修改源代碼,return true 時允許通路。修改NativeIO.java檔案中的557行的代碼,如下所示:

源代碼如下:

public static boolean access(String path, AccessRight desiredAccess)
    throws IOException {
    return access0(path, desiredAccess.accessRight());
}           

修改後的代碼如下:

public static boolean access(String path, AccessRight desiredAccess)
    throws IOException {
  return true;
    //return access0(path, desiredAccess.accessRight());
}           

再次執行,這個錯誤修複。

4.4 問題4

Caused by: java.io.FileNotFoundException: File /tmp/hive does not exist           

這個錯誤是說臨時目錄/tmp/hive需要有全部權限,即777權限,建立/tmp/hive 目錄,用winutils.exe對目錄賦權,如下

C:\Users\dongfangxiao>D:\spark_hadoop\hadoop-common\hadoop-common-2.6.0\bin\winutils.exe chmod -R 777 D:\tmp\hive

C:\Users\dongfangxiao>D:\spark_hadoop\hadoop-common\hadoop-common-2.6.0\bin\winutils.exe chmod -R 777 \tmp\hive           

4.5 問題5

Exception in thread "main" java.lang.NoSuchFieldError: METASTORE_CLIENT_SOCKET_LIFETIME           

OR

Exception in thread "main" java.lang.IllegalArgumentException: Unable to instantiate SparkSession with Hive support because Hive classes are not found           

原因是spark sql 讀取hive中繼資料需要的字段METASTORE_CLIENT_SOCKET_LIFETIME hive1.2.0開始才有,而我們引用的cdh版本的hive為1.1.0-cdh5.12.1,沒有該字段,故報錯。

Spark SQL when configured with a Hive version lower than 1.2.0 throws a java.lang.NoSuchFieldError for the field METASTORE_CLIENT_SOCKET_LIFETIME because this field was introduced in Hive 1.2.0 so its not possible to use Hive metastore version lower than 1.2.0 with Spark. The details of the Hive changes can be found here: https://issues.apache.org/jira/browse/HIVE-9508           

解決方法,引入第三方依賴

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-hive_2.11</artifactId>
    <version>2.1.0</version>
</dependency>           

4.6 問題6

Exception in thread "main" java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassNotFoundException: org.apache.hadoop.hive.ql.security.authorization.StorageBasedAuthorizationProvider,org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory           

解決方法,将window idea引入的hive-site.xml進行如下修改

<!--<property>-->
  <!--<name>hive.security.authorization.manager</name>-->
  <!--<value>org.apache.hadoop.hive.ql.security.authorization.StorageBasedAuthorizationProvider,org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value>-->
<!--</property>-->
<property>
<name>hive.security.authorization.manager</name>
<value>org.apache.hadoop.hive.ql.security.authorization.DefaultHiveAuthorizationProvider</value>
</property>           

5 總結

總結重要的幾點就是:

(1) 配置HADOOP_HOME,内帶winutils.exe 和 hadoop.dll 工具;

(2) 引入hive-site.xml等配置檔案,開發kerberos認證邏輯;

(3) 本地重寫NativeIO.java類;

(4) 給臨時目錄/tmp/hive賦予777權限;

(5) 引入第三方依賴spark-hive_2.11,要與spark版本對應;

(6) 本地hive-site.xml将hive.security.authorization.manager改為預設manager

最後提醒一點,本地調試隻是問了開發階段提高效率,避免每次修改都要打包送出到伺服器運作,但調試完,還是要打包到伺服器環境運作測試,沒問題才能上線。

至此,spark本地調試程式配置完成,以後就可以愉快地在本地調試spark on hadoop程式了。

6 參考

https://abgoswam.wordpress.com/2016/09/16/getting-started-with-spark-on-windows-10-part-2/

posted on 2019-07-01 18:21 XIAO的部落格 閱讀(...) 評論(...) 編輯 收藏