Hiveserver2源码剖析---如何实现代理用户

一、前言

本文主要关于基于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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值