一、hive并行执行多条sql(聚合)出现如下异常
- 使用的是1.1.0版本的hive-jdbc
- 所执行的sql包含: select count(1) from xxx 、 load 、insert等操作
异常1:
org.springframework.dao.DataAccessResourceFailureException: ConnectionCallback; SQL []; Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask; nested exception is java.sql.SQLException: Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
异常2:
org.apache.thrift.TApplicationException: ExecuteStatement failed: out of sequence response; nested exception is java.sql.SQLException: org.apache.thrift.TApplicationException: ExecuteStatement failed: out of sequence response
at com.sf.draw.openapi.service.task.BatchSamplingTask.lambda$joinAction$0(BatchSamplingTask.java:254)
at java.lang.Thread.run(Thread.java:748)
经过多天的测试,最后发现使用hive-jdbc 1.1.0时,不能同时执行两个以上的任务,必须等先前的任务执行完毕,才能提交新的任务,即需要串行执行;
测试代码为如下:
<!-- 数据源配置 -->
<beans:bean id="hiveDriver" class="org.apache.hive.jdbc.HiveDriver"/>
<beans:bean id="hiveDataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<beans:constructor-arg name="driver" ref="hiveDriver"/>
<beans:constructor-arg name="url" value="jdbc:hive2://192.168.80.103:10000/staff"/>
<beans:constructor-arg name="password" value="root"/>
<beans:constructor-arg name="username" value="root"/>
</beans:bean>
<hive-client-factory id="hiveClientFactory" hive-data-source-ref="hiveDataSource"/>
<hive-template id="hiveTemplate"/>
#hive 聚合操作
@RequestMapping("test")
public int selectFromHive() {
List<String> result = hiveTemplate.query("select count(1) from table1");
return result.size();
}
@RequestMapping("test1")
public int selectFromHive1() {
List<String> result = hiveTemplate.query("select count(1) from table2");
return result.size();
}
注:
- staff为hive中的一个数据库,table1和table2是其中的两个表。
- 依次访问函数selectFromHive()、selectFromHive1()将出现上述异常。
- sql串行执行则不会出现异常,如下:
@RequestMapping("test")
public int selectFromHive() {
List<String> result = hiveTemplate.query("select count(1) from table1");
List<String> result1 = hiveTemplate.query("select count(1) from table2");
return result.size()+result1.size();
}
二、解决方法
1、如果hive任务实时性要求低,可以使用含一个线程的线程池控制任务串行执行。
2,使用更高版本的hive-jdbc,如2.0.1,亲测可以同时提交多个sql执行。
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>2.0.1</version>
</dependency>
3、如果受限于hive(hdfs)的版本,不能更换hive-jdbc的版本,可以尝试将数据源Bean配置成多例(默认为单例)。
<beans:bean id="hiveDataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource" scope="prototype">
<beans:constructor-arg name="driver" ref="hiveDriver"/>
<beans:constructor-arg name="url" value="jdbc:hive2://192.168.80.103:10000/staff"/>
<beans:constructor-arg name="password" value="root"/>
<beans:constructor-arg name="username" value="root"/>
</beans:bean>
通过 scope="prototype" 将bean设置为多例,每次需要使用hiveDataSource时,spring容器均重新创建bean.
特别注意
hive-jdbc版本过高,将提示如下错误:
org.springframework.web.util.NestedServletException:Handler dispatch failed;
nested exception is java.lang.NoClassDefFoundError: org/apache/hadoop/hive/service/HiveServerException
at ....