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

2014-11-24 08:54:12 · 作者: · 浏览: 6
;
}
比如对于语句”select c1 from abc where c1 = 1;“,会依次调用Fetch Operator -> TableScanOperator -> FilterOperator -> SelectOperator -> ListSinkOperator
2. 类似”show tables/databases“这种DDL/DML语句,这种语句会先在本地FileSystem上创建一个scratch目录(由hive.exec.local.scratchdir配置),将计算结果写到本地scratch目录下,再通过FetchTask读取
3. 类似”select count(1) from tblname“这种会起MR Job的语句,会先在HDFS上创建scratch目录(由hive.exec.scratchdir配置),计算结果写到hdfs scratch目录下,再通过FetchTask读出来。
尝试多次后发现第一种类型的语句能返回结果,第二种第三种类型语句返回为空集合,而两者区别就在于是直接读取原表数据路径还是从scratch目录中读取。
HIVE在Compile环节会设置环境Context,创建local/hdfs scratch目录。在0.10版本之前,会存在一个问题,如果用户强制kill掉正在执行的语句,那么这些scratch dir就变成orphaned dir,未被清理。HIVE在0.10中加入了HIVE-3251来解决这个问题。
Driver中设置Context的HDFSCleanUp为true
[java]
command = new VariableSubstitution().substitute(conf,command);
ctx = new Context(conf);
ctx.setTryCount(getTryCount());
ctx.setCmd(command);
ctx.setHDFSCleanup(true);
获取和创建Scratch dir的时候将scratch dir path加入filesystem instance内部的deleteOnExit集合中
[java]
private String getScratchDir(String scheme, String authority, boolean mkdir, String scratchDir) {
String fileSystem = scheme + ":" + authority;
String dir = fsScratchDirs.get(fileSystem);
if (dir == null) {
Path dirPath = new Path(scheme, authority, scratchDir);
if (mkdir) {
try {
FileSystem fs = dirPath.getFileSystem(conf);
dirPath = new Path(fs.makeQualified(dirPath).toString());
if (!fs.mkdirs(dirPath)) {
throw new RuntimeException("Cannot make directory: "
+ dirPath.toString());
}
if (isHDFSCleanup) {
fs.deleteOnExit(dirPath);
}
} catch (IOException e) {
throw new RuntimeException (e);
}
}
dir = dirPath.toString();
fsScratchDirs.put(fileSystem, dir);
}
filesystem close的时候会先删除所有mark为deleteOnExit的files
[java]
public void close() throws IOException {
// delete all files that were marked as delete-on-exit.
processDeleteOnExit();
CACHE.remove(this.key, this);
}
同时我们知道FileSystem抽象类内部有个静态final成员变量Cache,以schema, authority, ugi, unique的组合为key缓存了filesystem instance,内部还有一个ClientFinalizer对象(实现了Runnable),注册到JVM的shutdown hook中,在JVM关闭的时候,会启动ClientFinalizer线程,依次关闭所有Cache中的filesystem,通过这种方式来清理删除与filesystem挂钩的资源文件,在Hive中这些挂钩的文件就是local/hdfs scratch
private class ClientFinalizer implements Runnable {
@Override
public synchronized void run() {
try {
closeAll(true);
} catch (IOException e) {
LOG.info("FileSystem.Cache.closeAll() threw an exception:\n" + e);
}
}
}
回到前面的问题,第二第三种类型语句通过在hive server执行端execute方法中打log能够确认数据是已经dump到scratch目录下了,但是在一进入fetchN方法的时候,发现这些文件就莫名奇妙消失了,从而导致读出来的是空数据。排查了很久发现是由于HIVE 0.10中引入了JIRA HIVE-3098(解决FileSystem Cache内存泄露的问题)所引起的。
每一个function call都会由一个HadoopThriftAuthBridge20S中的TUGIAssumingProcessor来处理,在process方法中会先创建一个proxyUser UGI,用clientUgi.doAs来执行具体的逻辑,这样daemon user会impersonate成client user,具体逻辑代码里面如果要创建一个filesystem对象,会通过UserGroupInformation.getCurrentUser()(即clientUgi)来作为FileSystem Cache Key的一部分加入Cache中。
HIVE-3098增加了process方法的finally中清除clientUGI在FileSystem.Cache中对应