如何在没有 ClassNotFound 异常的情况下在 Apache Tomcat 中配置 Impala/Hive2 JDBC 驱动程序

Posted

技术标签:

【中文标题】如何在没有 ClassNotFound 异常的情况下在 Apache Tomcat 中配置 Impala/Hive2 JDBC 驱动程序【英文标题】:How to configure Impala/Hive2 JDBC driver in Apache Tomcat without ClassNotFound exceptions 【发布时间】:2014-08-14 21:06:57 【问题描述】:

我正在尝试将 Impala/Hive2 JDBC 驱动程序添加到使用 Tomcat 7 (7.0.54) 部署的现有应用程序中。其他 JDBC 驱动程序工作正常(Oracle、MS SS、SyBase)。

但是,驱动程序从未连接,并且总是抛出不会被 Eclipse (Kepler) 中的 Java (JDK 1.7.0_55) 捕获的异常。这是在 Windows 8.1 Lenovo T500 笔记本电脑上完成的。没有有意义的错误消息或堆栈跟踪。

为了找出错误发生的位置,我获取了 Hive 源代码并制作了一个简单的 Java 程序来测试在 DEBUG 中单步执行的 JDBC 连接。缺少的类在 jar 中的引用错误比在 Clouder's documentation 中指定的要少。 HiveConnection.java (org.apache.hive.jdbc) 中有错误:

import org.apache.hadoop.hive.ql.session.SessionState;  
import org.apache.http.impl.client.DefaultHttpClient;  

我追踪了这些类存在的位置,并将以下 jar 添加到我制作的 UserLibrary 中:

hive-exec-0.12.0.jar     which contains the packages for ....hive.ql.....  
httpclient-4.2.5.jar     which contains the packages for ....http.impl.client....  

添加httpclient后,仍然出现引用错误

httpClient.addRequestInterceptor   - message =  The type org.apache.http.HttpRequestInterceptor cannot be resolved. It is indirectly referenced from required .class files

我将此追踪到:httpcore-4.2.4.jar

独立 Java 程序成功连接到 Impala 守护程序。我将这些 jar 与 JDBC 包一起作为 Java 源代码添加到 Tomcat /WEB-INF/ib/ 文件夹中。 Tomcat 遇到了一些问题,包括无法发布 IndexOutOfBounds 异常。我发现这主要是由于hadoop-common jar。我能够通过彻底清理 Tomcat 定义和项目并将这个 jar 添加为最后一个来发布它。还是试了几次。

然后,运行应用程序也停止,但在 DriverManager.getConnection(connstr) 处出现异常。这些错误总是与没有看到加载到 /WEB-INF/lib/ 文件夹中的 jar 文件中的各种类有关。删除然后重新导入它们按以下顺序遍历这些错误:

org/apache/http/client/httpclient      (in httpclient jar)  
org/apache/http/httprequestinterceptor (in httpcore jar)  
org/apache/hadoop/conf/configuration   (in hadoop-common jar)  
org/apache/hadoop/hive/conf/hiveconf   (in hive-common AND hive-exec jars)  

HIVE_CLI_SERVICE_PROTOCOL_V6 的最后一个奇怪错误。后者很难追踪,直到我在 HiveConnection.java 的 Java 代码中看到它,其中 HIVE_CLI_SERVICE_PROTOCOL_Vx 被添加到支持的协议集合中。这用于检查来自 Impala 的响应,如果 Impala 使用不在列表中的响应,则连接被取消。在我拥有的版本中,使用了 V1-V3。我发现 SVN 上的最新源代码是 V7,但这些在 CDH5 附带的 JDBC 代码中没有使用。

执行另一个循环,删除所有内容,然后将库 jars 和 JDBC 源代码(所以没有添加 JDBC jar)添加到我的 Tomcat Java/src 文件夹中的包中:

org.apache.hadoop.hive.jdbc     (Hive 1 driver)  
org.apache.hive.jdbc            (Hive 2 driver)  

终于,我能够在 DEBUG 中单步调试 HiveConnection 并成功进行通信,并且可以检查来自 Impala 的响应。它响应它正在使用____V1 协议,因此它被接受了。

由于文档声明只需要一些 jar,但我发现需要更多的 jar 来满足导入语句,我如何配置 Tomcat 以便仅使用分布式 JDBC 驱动程序及其支持 jar?我怀疑Tomcat如何进行类加载可能存在问题,因为我注意到Catalina.jar及其类加载器中发生了杀手级异常(没有源代码,所以我不知道确切的位置或原因)。

【问题讨论】:

【参考方案1】:

我能够从 Tomcat 连接到 Impala(尽管我使用的是 Tomcat 8,而不是 7)。 我将所有这些 jar 复制到 tomcats lib 目录:

commons-logging-1.1.3.jar          
hive-metastore-0.12.0-cdh5.0.2.jar 
libfb303-0.9.0.jar          
slf4j-log4j12.jar
hadoop-common-2.3.0-cdh5.0.2.jar   
hive-service-0.12.0-cdh5.0.2.jar   
libthrift-0.9.0.cloudera.2.jar
hive-common-0.12.0-cdh5.0.2.jar    
httpclient-4.2.5.jar               
log4j-1.2.16.jar
hive-jdbc-0.12.0-cdh5.0.2.jar      
httpcore-4.2.5.jar                 
slf4j-api-1.7.5.jar

【讨论】:

感谢您的评论。我刚刚做了一个关于 Cloudera 的数据科学分布的网络广播 (TechLab)。我注意到的一件事是另一个未记录的库依赖问题,即为 HDFS 和 YARN 操作编写自定义 Java。给那些认为这只是使用 Maven 的问题的人的快速消息:它不是。拥有未记录的库依赖项是不行的。在这种情况下,奇怪的解决方案是引用整个 hadoop lib jar 文件夹。有效。我没有时间穿过雷区。

以上是关于如何在没有 ClassNotFound 异常的情况下在 Apache Tomcat 中配置 Impala/Hive2 JDBC 驱动程序的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 DataflowRunner 时出现 ClassNotFound 异常

Apache Oozie 在创建 mysql DB 时抛出 classnotfound 异常

从 apache Spark 运行 java 程序时出现 ClassNotFound 异常

Faces Servlet - ClassNotFound 异常 [重复]

h2 数据库的 ClassNotFound 异常 class.forname("org.h2.Driver")

Tomcat如何打破双亲委托机制?