一、前言
本文主要关于基于hive2.3.6版本的hiveserver2源码部分剖析。
二、背景
前段时间做chdfs迁移,发现beeline连接hiveserver2的用户在hdfs创建的临时目录变成了hive。其中代理用户并未起效果,感觉chdfs有代理用户上的bug。然后翻看了下hiveserver2服务端和客户端连接的代码。(hive.server2.enable.doAs 已经设置为 true)
正常情况下:

代理用户不起效果:

三、服务端启动
1、Hiveserver2
public static void main(String[] args) {
// 加载配置文件
HiveConf.setLoadHiveServer2Config(true);
try {
ServerOptionsProcessor oproc = new ServerOptionsProcessor("hiveserver2");
// 返回 StartOptionExecutor
ServerOptionsProcessorResponse oprocResponse = oproc.parse(args);
// NOTE: It is critical to do this here so that log4j is reinitialized
// before any of the other core hive classes are loaded
String initLog4jMessage = LogUtils.initHiveLog4j();
LOG.debug(initLog4jMessage);
HiveStringUtils.startupShutdownMessage(HiveServer2.class, args, LOG);
// Logger debug message from "oproc" after log4j initialize properly
LOG.debug(oproc.getDebugMessage().toString());
// Call the executor which will execute the appropriate command based on the parsed options
// 执行 StartOptionExecutor.execute()
oprocResponse.getServerOptionsExecutor().execute();
} catch (LogInitializationException e) {
LOG.error("Error initializing log: " + e.getMessage(), e);
System.exit(-1);
}
}
static class StartOptionExecutor implements ServerOptionsExecutor {
@Override
public void execute() {
try {
// 开启hiveserver2 thrift
startHiveServer2();
} catch (Throwable t) {
LOG.error("Error starting HiveServer2", t);
System.exit(-1);
}
}
}
private static void startHiveServer2() throws Throwable {
long attempts = 0, maxAttempts = 1;
while (true) {
LOG.info("Starting HiveServer2");
HiveConf hiveConf = new HiveConf();
// 最大启动重试次数
maxAttempts = hiveConf.getLongVar(HiveConf.ConfVars.HIVE_SERVER2_MAX_START_ATTEMPTS);
// 两次重试之间的时间间隔
long retrySleepIntervalMs = hiveConf
.getTimeVar(ConfVars.HIVE_SERVER2_SLEEP_INTERVAL_BETWEEN_START_ATTEMPTS,
TimeUnit.MILLISECONDS);
HiveServer2 server = null;
try {
// Initialize the pool before we start the server; don't start yet.
TezSessionPoolManager sessionPool = null;
if (hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_TEZ_INITIALIZE_DEFAULT_SESSIONS)) {
sessionPool = TezSessionPoolManager.getInstance();
sessionPool.setupPool(hiveConf);
}
// Cleanup the scratch dir before starting
// 清理scratchdir 默认hdfs目录 /tmp/hive
ServerUtils.cleanUpScratchDir(hiveConf);
// Schedule task to cleanup dangling scratch dir periodically,
// initial wait for a random time between 0-10 min to
// avoid intial spike when using multiple HS2
// 定时服务清理hive不正常关闭遗留的目录,通过判断 inuse.lck 来判断目录是否被锁住,未被锁定自动清理
scheduleClearDanglingScratchDir(hiveConf, new Random().nextInt(600));
server = new HiveServer2();
// 初始化,主要添加两个服务:1、CLIService 2、ThriftBinaryCLIService 3、启动webui server
server.init(hiveConf);
// 启动服务
server.start();
try {
JvmPauseMonitor pauseMonitor = new JvmPauseMonitor(hiveConf);
pauseMonitor.start();
} catch (Throwable t) {
LOG.warn("Could not initiate the JvmPauseMonitor thread." + " GCs and Pauses may not be " +
"warned upon.", t);
}
if (sessionPool != null) {
sessionPool.startPool();
}
if (hiveConf.getVar(ConfVars.HIVE_EXECUTION_ENGINE).equals("spark")) {
SparkSessionManagerImpl.getInstance().setup(hiveConf);
}
break;
} catch (Throwable throwable) {
if (server != null) {
try {
server.stop();
} catch (Throwable t) {
LOG.info("Exception caught when calling stop of HiveServer2 before retrying start", t);
} finally {
server = null;
}
}
if (++attempts >= maxAttempts) {
throw new Error("Max start attempts " + maxAttempts + " exhausted", throwable);
} else {
LOG.warn("Error starting HiveServer2 on attempt " + attempts
+ ", will retry in " + retrySleepIntervalMs + "ms", throwable);
try {
Thread.sleep(retrySleepIntervalMs);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
CliService
public synchronized void init(HiveConf hiveConf) {
this.hiveConf = hiveConf;
// session管理服务
sessionManager = new SessionManager(hiveServer2);
// 每批次返回给client的条数默认1000
defaultFetchRows = hiveConf.getIntVar(ConfVars.HIVE_SERVER2_THRIFT_RESULTSET_DEFAULT_FETCH_SIZE);
addService(sessionManager);
// If the hadoop cluster is secure, do a kerberos login for the service from the keytab
if (UserGroupInformation.isSecurityEnabled()) {
try {
HiveAuthFactory.loginFromKeytab(hiveConf);
this.serviceUGI = Utils.getUGI();
} catch (IOException e) {
throw new ServiceException("Unable to login to kerberos with given principal/keytab", e);
} catch (LoginException e) {
throw new ServiceException("Unable to login to kerberos with given principal/keytab", e);
}
// Also try creating a UGI object for the SPNego principal
String principal = hiveConf.getVar(ConfVars.HIVE_SERVER2_SPNEGO_PRINCIPAL);
String keyTabFile = hiveConf.getVar(ConfVars.HIVE_SERVER2_SPNEGO_KEYTAB);
if (principal.isEmpty() || keyTabFile.isEmpty()) {
LOG.info("SPNego httpUGI not created, spNegoPrincipal: " + principal +
", ketabFile: " + keyTabFile);
} else {
try {
this.httpUGI = HiveAuthFactory.loginFromSpnegoKeytabAndReturnUGI(hiveConf);
LOG.info("SPNego httpUGI successfully created.");
} catch (IOException e) {
LOG.warn("SPNego httpUGI creation failed: ", e);
}
}
}
// creates connection to HMS and thus *must* occur after kerberos login above
try {
// 初始化hive SessionState 此时用户未hive。还没有代理用户
applyAuthorizationConfigPolicy(hiveConf);
} catch (Exception e) {
throw new RuntimeException("Error applying authorization policy on hive configuration: "
+ e.getMessage(), e);
}
setupBlockedUdfs();
super.init(hiveConf);
}
ThriftBinaryCLIService
public void run() {
try {
// Server thread pool
String threadPoolName = "HiveServer2-Handler-Pool";
ExecutorService executorService = new ThreadPoolExecutorWithOomHook(minWorkerThreads,
maxWorkerThreads, workerKeepAliveTime, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), new ThreadFactoryWithGarbageCleanup(threadPoolName),
oomHook);
// Thrift configs
hiveAuthFactory = new HiveAuthFactory(hiveConf);
// 里面加了callback 做账号密码校验,自定义实现 PasswdAuthenticationProvider
TTransportFactory transportFactory = hiveAuthFactory.getAuthTransFactory();
// TCLIService.Processor thift服务端处理接口
TProcessorFactory processorFactory = hiveAuthFactory.getAuthProcFactory(this);
TServerSocket serverSocket = null;
List<String> sslVersionBlacklist = new ArrayList<String>();
for (String sslVersion : hiveConf.getVar(ConfVars.HIVE_SSL_PROTOCOL_BLACKLIST).split(",")) {
sslVersionBlacklist.add(sslVersion);
}
if (!hiveConf.getBoolVar(ConfVars.HIVE_SERVER2_USE_SSL)) {
serverSocket = HiveAuthUtils.getServerSocket(hiveHost, portNum);
} else {
String keyStorePath = hiveConf.getVar(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH).trim();
if (keyStorePath.isEmpty()) {
throw new IllegalArgumentException(ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PATH.varname
+ " Not configured for SSL connection");
}
String keyStorePassword = ShimLoader.getHadoopShims().getPassword(hiveConf,
HiveConf.ConfVars.HIVE_SERVER2_SSL_KEYSTORE_PASSWORD.varname);
serverSocket = HiveAuthUtils.getServerSSLSocket

最低0.47元/天 解锁文章
400

被折叠的 条评论
为什么被折叠?



