OrcRelation 不可分配给 HadoopFsRelation

Jaf*_*son 4 java hive apache-spark apache-spark-sql

我正在尝试在配置单元表上运行 SparkSql。但我无法理解的问题。这是我的代码:

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.hive.*;
import org.apache.spark.sql.SQLContext;
public class queryhive {
public static void main(String[] args)
{
    //SparkSession sc = new SparkConf().setAppName("SparkSessionZipsExample").setMaster("local");
    SparkConf sparkConf = new SparkConf().setAppName("SparkSessionZipsExample").setMaster("local");
        JavaSparkContext scon = new JavaSparkContext(sparkConf);
            SQLContext sqlContext = new SQLContext(scon);
        String warehouseLocation = "file:${system:user.dir}/spark-warehouse";
            SparkSession sc = SparkSession
               .builder()
               .appName("SparkSessionZipsExample")
               .config("spark.sql.warehouse.dir", warehouseLocation)
               .enableHiveSupport()
               .getOrCreate();
            HiveContext hc = new org.apache.spark.sql.hive.HiveContext(sc);
            hc.sql("select count(*) from SparkHive.health");
            Row[] results = (Row[]) sqlContext.sql("FROM src SELECT key, value").collect();
}
}
Run Code Online (Sandbox Code Playgroud)

我得到的例外是:

17/02/16 16:36:51 INFO SparkSqlParser: Parsing command: select count(*) from SparkHive.health
Exception in thread "main" java.util.ServiceConfigurationError: org.apache.spark.sql.sources.DataSourceRegister: Provider org.apache.spark.sql.hive.orc.DefaultSource could not be instantiated
    at java.util.ServiceLoader.fail(ServiceLoader.java:232)
    at java.util.ServiceLoader.access$100(ServiceLoader.java:185)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384)
    at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
    at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
    at scala.collection.convert.Wrappers$JIteratorWrapper.next(Wrappers.scala:43)
    at scala.collection.Iterator$class.foreach(Iterator.scala:893)
    at scala.collection.AbstractIterator.foreach(Iterator.scala:1336)
    at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
    at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
    at scala.collection.TraversableLike$class.filterImpl(TraversableLike.scala:247)
    at scala.collection.TraversableLike$class.filter(TraversableLike.scala:259)
    at scala.collection.AbstractTraversable.filter(Traversable.scala:104)
    at org.apache.spark.sql.execution.datasources.DataSource$.lookupDataSource(DataSource.scala:550)
    at org.apache.spark.sql.execution.datasources.DataSource.providingClass$lzycompute(DataSource.scala:86)
    at org.apache.spark.sql.execution.datasources.DataSource.providingClass(DataSource.scala:86)
    at org.apache.spark.sql.execution.datasources.DataSource.resolveRelation(DataSource.scala:325)
    at org.apache.spark.sql.execution.datasources.ResolveDataSource$$anonfun$apply$1.applyOrElse(rules.scala:58)
    at org.apache.spark.sql.execution.datasources.ResolveDataSource$$anonfun$apply$1.applyOrElse(rules.scala:41)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$resolveOperators$1.apply(LogicalPlan.scala:61)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$resolveOperators$1.apply(LogicalPlan.scala:61)
    at org.apache.spark.sql.catalyst.trees.CurrentOrigin$.withOrigin(TreeNode.scala:70)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan.resolveOperators(LogicalPlan.scala:60)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$1.apply(LogicalPlan.scala:58)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan$$anonfun$1.apply(LogicalPlan.scala:58)
    at org.apache.spark.sql.catalyst.trees.TreeNode$$anonfun$5.apply(TreeNode.scala:331)
    at org.apache.spark.sql.catalyst.trees.TreeNode.mapProductIterator(TreeNode.scala:188)
    at org.apache.spark.sql.catalyst.trees.TreeNode.transformChildren(TreeNode.scala:329)
    at org.apache.spark.sql.catalyst.plans.logical.LogicalPlan.resolveOperators(LogicalPlan.scala:58)
    at org.apache.spark.sql.execution.datasources.ResolveDataSource.apply(rules.scala:41)
    at org.apache.spark.sql.execution.datasources.ResolveDataSource.apply(rules.scala:40)
    at org.apache.spark.sql.catalyst.rules.RuleExecutor$$anonfun$execute$1$$anonfun$apply$1.apply(RuleExecutor.scala:85)
    at org.apache.spark.sql.catalyst.rules.RuleExecutor$$anonfun$execute$1$$anonfun$apply$1.apply(RuleExecutor.scala:82)
    at scala.collection.LinearSeqOptimized$class.foldLeft(LinearSeqOptimized.scala:124)
    at scala.collection.immutable.List.foldLeft(List.scala:84)
    at org.apache.spark.sql.catalyst.rules.RuleExecutor$$anonfun$execute$1.apply(RuleExecutor.scala:82)
    at org.apache.spark.sql.catalyst.rules.RuleExecutor$$anonfun$execute$1.apply(RuleExecutor.scala:74)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at org.apache.spark.sql.catalyst.rules.RuleExecutor.execute(RuleExecutor.scala:74)
    at org.apache.spark.sql.execution.QueryExecution.analyzed$lzycompute(QueryExecution.scala:64)
    at org.apache.spark.sql.execution.QueryExecution.analyzed(QueryExecution.scala:62)
    at org.apache.spark.sql.execution.QueryExecution.assertAnalyzed(QueryExecution.scala:48)
    at org.apache.spark.sql.Dataset$.ofRows(Dataset.scala:63)
    at org.apache.spark.sql.SparkSession.sql(SparkSession.scala:592)
    at org.apache.spark.sql.SQLContext.sql(SQLContext.scala:699)
    at SparkHiveSql.sparkhivesql.queryhive.main(queryhive.java:27)
Caused by: java.lang.VerifyError: Bad return type
Exception Details:
  Location:
    org/apache/spark/sql/hive/orc/DefaultSource.createRelation(Lorg/apache/spark/sql/SQLContext;[Ljava/lang/String;Lscala/Option;Lscala/Option;Lscala/collection/immutable/Map;)Lorg/apache/spark/sql/sources/HadoopFsRelation; @35: areturn
  Reason:
    Type 'org/apache/spark/sql/hive/orc/OrcRelation' (current frame, stack[0]) is not assignable to 'org/apache/spark/sql/sources/HadoopFsRelation' (from method signature)
  Current Frame:
    bci: @35
    flags: { }
    locals: { 'org/apache/spark/sql/hive/orc/DefaultSource', 'org/apache/spark/sql/SQLContext', '[Ljava/lang/String;', 'scala/Option', 'scala/Option', 'scala/collection/immutable/Map' }
    stack: { 'org/apache/spark/sql/hive/orc/OrcRelation' }
  Bytecode:
    0x0000000: b200 1c2b c100 1ebb 000e 592a b700 22b6
    0x0000010: 0026 bb00 2859 2c2d b200 2d19 0419 052b
    0x0000020: b700 30b0                              

    at java.lang.Class.getDeclaredConstructors0(Native Method)
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671)
    at java.lang.Class.getConstructor0(Class.java:3075)
    at java.lang.Class.newInstance(Class.java:412)
    at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380)
    ... 43 more
17/02/16 16:36:55 INFO SparkContext: Invoking stop() from shutdown hook
17/02/16 16:36:55 INFO SparkUI: Stopped Spark web UI at http://10.0.0.3:4040
Run Code Online (Sandbox Code Playgroud)

I do not know why is this happening. Before running this program, my HIVE was working fine, but now it is not working at all.
What is the reason and how I make the above code run?
I am using Eclispe IDE and my Spark version is 2.1.0

G_H*_*G_H 5

您的类路径中很可能存在一些版本冲突。为了理解发生了什么,我将简要解释 Java 服务提供者机制。

在 Java 中,服务提供者机制允许 API 指定一些(抽象)类,API 的实现必须子类化。ServiceLoader然后可以使用A来查找提供程序类的实现。此类类的一个示例是来自 Java API 的JAXBContext。JAXB 本身是您将在应用程序中使用的 API,但有多个 JAXB 实现(参考实现和 EclipseLink Moxy)。抽象类(本例中为 JAXBContext)是 API 的入口点。服务提供者机制可以找到实现的一种方法是通过类路径上特殊文件夹中的文件:META-INF/services. 您通常会在 jar 文件中找到此类文件夹。services 文件夹可以包含具有抽象提供者类名称的文件。可能有多个这样的文件。每个文件可以包含任意数量的特定类名,它们是抽象类的实现。

因此,对于 JAXB,您会javax.xml.bind.JAXBContext在 jar 文件中找到带有文件名的文件。那是抽象提供者类的名称。然后这些文件将包含一行或多行列出 JAXBContext 的实现,这些实现可以被实例化以向该提供者提供一个条目。

让我们看看您的堆栈跟踪。在某些时候,一个名为的类DataSource希望找到实现。它发生在堆栈中:

at org.apache.spark.sql.execution.datasources.DataSource$.lookupDataSource(DataSource.scala:550)
at org.apache.spark.sql.execution.datasources.DataSource.providingClass$lzycompute(DataSource.scala:86)
at org.apache.spark.sql.execution.datasources.DataSource.providingClass(DataSource.scala:86)
at org.apache.spark.sql.execution.datasources.DataSource.resolveRelation(DataSource.scala:325)
Run Code Online (Sandbox Code Playgroud)

java.util.ServiceLoader类是通过已经经由上述机制被注册实现用于迭代。它遍历实现列表,直到根据调用代码的某些标准找到某些内容。这发生在这里:

at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384)
at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404)
at java.util.ServiceLoader$1.next(ServiceLoader.java:480)
Run Code Online (Sandbox Code Playgroud)

这就是事情出错的地方。问题的详细信息可以在这部分找到:

Location:
org/apache/spark/sql/hive/orc/DefaultSource.createRelation(Lorg/apache/spark/sql/SQLContext;[Ljava/lang/String;Lscala/Option;Lscala/Option;Lscala/collection/immutable/Map;)Lorg/apache/spark/sql/sources/HadoopFsRelation; @35: areturn
Reason:
Type 'org/apache/spark/sql/hive/orc/OrcRelation' (current frame, stack[0]) is not assignable to 'org/apache/spark/sql/sources/HadoopFsRelation' (from method signature)
Current Frame:
bci: @35
flags: { }
locals: { 'org/apache/spark/sql/hive/orc/DefaultSource', 'org/apache/spark/sql/SQLContext', '[Ljava/lang/String;', 'scala/Option', 'scala/Option', 'scala/collection/immutable/Map' }
stack: { 'org/apache/spark/sql/hive/orc/OrcRelation' }
Run Code Online (Sandbox Code Playgroud)

这需要一些挖掘,但您可以从中推断出org.apache.spark.sql.hive.orc.DefaultSource发现一个类,据称该类实现了调用所寻找的内容。创建它的一个实例,createRelation然后用它调用一个方法。该方法org.apache.spark.sql.sources.HadoopFsRelation至少根据抽象类具有返回类型。然而,返回的是一个 class org.apache.spark.sql.hive.orc.OrcRelation。如果它是 HadoopFsRelation 的子类,那很好,但显然不是。

最有可能发生这种情况的情况是,如果同一类的不同实现最终出现在类路径上,并且您获得的实现具有不同的方法返回类型,或者只是具有不同(不兼容)的类层次结构。

我去寻找类 HadoopFsRelation。它可以在 Spark 1.6.3 版本之前的包中找到org.apache.spark.sql.sources。在 2.1.0 版本中它不再存在,所以我怀疑它已从 2.x API 中删除。在 1.6.3 版本中,您还会找到 class org.apache.spark.sql.hive.orc.OrcRelation,并且在该版本中它确实实现了 HadoopFsRelation。

现在到 Spark 2.1.0 版。类 HadoopFsRelation 无处可寻。我在与以前相同的包中找到了 OrcRelation(在 jar spark-hive_2.11-2.1.0.jar 中,它是 Spark 2.1.0 发行版的一部分)。只是现在该类没有实现 HadoopFsRelation。

所以正在发生的事情是这样的。您尝试在带有 Hive 的代码中使用 Spark。SQLContext您创建的类可能是从 Spark 1.6.x(或早于 2.x 的其他版本)加载的。它会寻找 DataSourceRegister 实现(被列为服务提供者的类)并找到一个META-INF/services/org.apache.spark.sql.sources.DataSourceRegister文件(或多个,更有可能)。它决定它需要的是实现org.apache.spark.sql.hive.orc.DefaultSource。找到并实例化该类。到现在为止还挺好。然后 1.6.x 代码调用createRelation它并期望HadoopFsRelation实现。但是,返回org.apache.spark.sql.hive.orc.OrcRelation的类从版本 2.1.0(或 2 之后的任何版本)加载,它没有实现 HadoopFsRelation。

如果您已经安装了 Spark 2.1.0 并使用了它的库,然后添加了一些您下载的库,我敢打赌您已经下载了一些 2.x 之前的版本。这些最终成为执行代码时的入口点,但他们意外地找到了具有不同定义的较新类。您需要检查类路径上的内容并删除不正确的条目。最好删除与 Spark、Hive 和 Hadoop 相关的所有内容,并确保仅使用安装中的内容,或通过 Apache 下载最新版本,检查您是否针对其 API 进行编码并仅使用这些 jar。如果您需要任何额外的东西,请确保它来自相同的版本,或者它是与您使用的版本兼容的某些实用程序。