hive0.11的hive server实现kerberos认证和impersonation中碰到的问题(一)

2014-11-24 08:54:12 · 作者: · 浏览: 0
背景
最近在做hive0.9升级到0.11的工作,其中一个步骤就是将之前apply到0.9的patch re-apply到0.11中,有一个patch(https://github.com/lalaguozhe/hive/commit/f2892f9e4706f3ea04117cbc7e7f54ff6af1e415)参考了hive metastore service的实现,对hive server增加了sasl kerberos认证,支持impersonate成client ugi的身份来启动作业(默认方式会以起hive service daemon的用户身份来执行,导致所有query共用一个用户启动作业)。
发现的问题
不过在re-apply这个patch后发现,用jdbc client访问hive server对于某些语句返回的是空结果集(HiveQueryResultSet中的fetchedRows是个空集合),中间也没有任何报错。非常奇怪,通过多次尝试定位出只有一种case的语句会正常返回结果,即类似“select * from xxx where yyy”这种不会起MapReduce Job的语句,其他“show tables/databases”,“select a from xxx”等语句都返回为空结果集。
调研
Hive jdbc client(底层是thrift client)在提交一条语句的时候会经历如下过程:
1. 构建execute_args对象,里面封装了要执行的语句,发送远程方法名execute和execute_args对象,接收execute返回结果,这时候client已经获取了column names和column types信息。
[java]
public void send_execute(String query) throws org.apache.thrift.TException
{
execute_args args = new execute_args();
args.setQuery(query);
sendBase("execute", args);
}
server端由HiveServerHandler来处理,对应的execute方法会new一个driver,调用driver.run(cmd)来执行具体的语句
2. 多次发送远程方法名fetchN和最大返回记录数numRows,返回的结果集会放在List fetchedRows中。比如一共要返回90条record,每次fetchN最多返回50条,则一共调用了两次fetchN
[java]
public void send_fetchN(int numRows) throws org.apache.thrift.TException
{
fetchN_args args = new fetchN_args();
args.setNumRows(numRows);
sendBase("fetchN", args);
}
server端HiveServerHandler中的fetchN会调用driver.getResult(), 由QueryPlan的FetchTask中的FetchOperator获取存放结果集的文件路径,得到InputFormat信息,有了InputFormat就可以调用getSplits方法获取一串InputSplit,依次获取每一个InputSplit的RecordReader,迭代next获取key/value值(value代表每行结果record)
3. HiveConnection close,发送clean远程方法名
[java]
public void send_clean() throws org.apache.thrift.TException
{
clean_args args = new clean_args();
sendBase("clean", args);
}
server端执行clean方法,close掉driver并对context做一些清理工作,删除语句产生的scratch directories (local file system和hdfs上的都会清除)
Context.java的removeScratchDir方法
[java]
private void removeScratchDir() {
for (Map.Entry entry : fsScratchDirs.entrySet()) {
try {
Path p = new Path(entry.getValue());
p.getFileSystem(conf).delete(p, true);
} catch (Exception e) {
LOG.warn("Error Removing Scratch: "
+ StringUtils.stringifyException(e));
}
}
fsScratchDirs.clear();
}
具体定位语句可以分为三种情况:
1. 针对”select * from xxx“这种不起MR Job的语句,server端是直接通过MetastoreClient拿到了表对应hdfs的存放路径用FetchTask读取出来的。这边有点要注意的是hive 0.11中新增加了一个配置项”hive.fetch.task.conversion“,由jira HIVE-887引入,默认值是minimal,此外可以设置成more,minimal模式下对于”SELECT STAR, FILTER on partition columns, LIMIT only“不会起MR Job,more模式下对于”SELECT, FILTER, LIMIT only (TABLESAMPLE, virtual columns)“这种没有子查询,聚合操作和distinct的语句也不会起MR Job,大大降低了query latency,观察实现代码,其实它是将TableScanOperator, FilterOperator, SelectOperator作为FetchOperator的子Operator将数据拿到client端(即hive server端)来做filter或者projection
FetchOperator中保存了Operator Tree信息,类似深度遍历调用operator.process()方法。
FetchOperator.java
[java]
public boolean pushRow() throws IOException, HiveException {
InspectableObject row = getNextRow();
if (row != null) {
operator.process(row.o, 0);
}
return row != null