Hive相关的两个疑问[一]

  从疑问出发,寻根问底探究原理:
1. Hive CLI/Hive Beeline/Hive JDBC断开连接之后,运行在Yarn上的任务是否继续运行?
2. 我们知道JDBC是无法做缓存的,那么HUE是如何实现缓存功能的?

  本部分研究第一个问题,即客户端的状态是否影响Yarn上正在运行的任务。

  首先我们从现象谈起然后逐渐找到问题的答案,既是一个解疑的过程也是一个探究研究问题思路的过程,更是一个增长知识的过程。

1. 现象描述

  在Hadoop生态中执行Hive任务时,经常会出现各种各样的问题。今天发现了一个特别有意思的事情,执行调度的同学说他们执行的任务,在beeline调用端任务失败,但业务同学去数据库查看相应的数据记录,初步发现没有异常同步成功。这就引起了一个问题:当beeline异常断开时,当前运行的yarn的任务是否同步退出?还是继续执行完成?

  根据这个问题,我首先做了现象的重现,结果发现:断开连接之后,执行在yarn上的任务会同步结束。分别通过HIVE CLI、Beeline、JDBC三种方式做得测试,结果都表明断开连接之后,任务无法接续运行。除了一种情况那就是HIVE CLI模式下,直接通过KILL命令杀死Hive进程,Hive客户端的JVM直接退出,但正在Yarn上运行的任务未退出继续运行,直到结束。

2. Hive三种方式访问Hive路径

Hive的三种访问方式
其中Hive Beeline使用的也是Thrift API访问方式。

3. 寻根问底

3.1. [Hive CLI]方式

  1. org.apache.hadoop.hive.cli.CliDriver
  2. ctrl+c方式断开:
    CliDriver注册了信号处理:
private boolean interruptRequested;

@Override
public void handle(Signal signal) {
  boolean initialRequest = !interruptRequested;
  interruptRequested = true;

  // Kill the VM on second ctrl+c
  if (!initialRequest) {
    console.printInfo("Exiting the JVM");
    System.exit(127);
  }

  // Interrupt the CLI thread to stop the current statement and return to prompt
  console.printInfo("Interrupting... Be patient, this might take some time.");
  console.printInfo("Press Ctrl+C again to kill JVM");

  // First, kill any running MR jobs
  HadoopJobExecHelper.killRunningJobs();
  TezJobExecHelper.killRunningJobs();
  HiveInterruptUtils.interrupt();
}

  通过以上的源码可以看出如果我们使用ctrl+c命令,那么触发Kill操作,依次处理了 HadoopJob、TezJob以及Hive的退出操作;如果前后两次使用ctrl+c命令,那么直接Kill JVM。
3. 直接Kill -9方式退出Hive:针对Yarn MR任务模式,对于LocalMRJob不做讨论。
通过阅读源码:

} else if (cmd_trimmed.startsWith("!")) {

String shell_cmd = cmd_trimmed.substring(1);
shell_cmd = new VariableSubstitution(new HiveVariableSource() {
  @Override
  public Map<String, String> getHiveVariable() {
    return SessionState.get().getHiveVariables();
  }
}).substitute(ss.getConf(), shell_cmd);

// shell_cmd = "/bin/bash -c \'" + shell_cmd + "\'";
try {
  ShellCmdExecutor executor = new ShellCmdExecutor(shell_cmd, ss.out, ss.err);
  ret = executor.execute();
  if (ret != 0) {
    console.printError("Command failed with exit code = " + ret);
  }
} catch (Exception e) {
  console.printError("Exception raised from Shell command " + e.getLocalizedMessage(),
    stringifyException(e));
  ret = 1;
}
 }  else { // local mode

可以看出CliDriver对于命令的处理是通过调用外部线程进行的。如果直接结束JVM,那么外部线程没有影响继续运行,所以我们看到的表象就是人物继续运行知道运行结束。

3.2. Beeline:thrift server方式访问Hive

  1. 访问主类:Beeline: org.apache.hive.beeline.BeeLine
  2. 通过ctrl+c方式断开:通过ctrl+c方式断开连接,Hive会捕捉到相应的信号,从而进行相关处理。信号处理的handler定义如下
  private Statement stmt = null;

  SunSignalHandler () {
    // Interpret Ctrl+C as a request to cancel the currently
    // executing query.
    Signal.handle (new Signal ("INT"), this);
  }

  public void setStatement(Statement stmt) {
    this.stmt = stmt;
  }

  public void handle (Signal signal) {
    try {
      if (stmt != null) {
        stmt.cancel();
      }
    } catch (SQLException ex) {
      // ignore
    }
  }

  从处理的代码中可以看出,如果出现ctrl+c信号,Hive会取消目前相关操作。
3. 异常断开:包括超时、宕机等异常情况
如果是Thrift RPC的连接断开,那么从源码中可以看出

HIVE_SERVER2_CLOSE_SESSION_ON_DISCONNECT("hive.server2.close.session.on.disconnect", true,
      "Session will be closed when connection is closed. Set this to false to have session outlive its parent connection.")

如果connection断开,那么session会立马被关闭。而HiveServer2关闭session的操作,如下所示

ThriftCLIServerContext context = (ThriftCLIServerContext) serverContext;
SessionHandle sessionHandle = context.getSessionHandle();
if (sessionHandle != null) {
  LOG.info("Session disconnected without closing properly. ");
  try {
    boolean close = cliService.getSessionManager().getSession(sessionHandle).getHiveConf()
      .getBoolVar(ConfVars.HIVE_SERVER2_CLOSE_SESSION_ON_DISCONNECT);
    LOG.info((close ? "" : "Not ") + "Closing the session: " + sessionHandle);
    if (close) {
      cliService.closeSession(sessionHandle);
    }
  } catch (HiveSQLException e) {
    LOG.warn("Failed to close session: " + e, e);
  }
}

此处cliService的关闭最终会导致HiveSessionImpl的关闭操作,其中关闭路径为:CLIService.closeSession–>SessionManager.closeSession–> HiveSession.close

  try {
      acquire(true, false);
      // Iterate through the opHandles and close their operations
      List<OperationHandle> ops = null;
      synchronized (opHandleSet) {
        ops = new ArrayList<>(opHandleSet);
        opHandleSet.clear();
      }
      for (OperationHandle opHandle : ops) {
        operationManager.closeOperation(opHandle);
      }
      // Cleanup session log directory.
      cleanupSessionLogDir();
      HiveHistory hiveHist = sessionState.getHiveHistory();
      if (null != hiveHist) {
        hiveHist.closeStream();
      }
      try {
        sessionState.resetThreadName();
        sessionState.close();
      } finally {
        sessionState = null;
      }
    } catch (IOException ioe) {
      throw new HiveSQLException("Failure to close", ioe);
    } finally {
      if (sessionState != null) {
        try {
          sessionState.resetThreadName();
          sessionState.close();
        } catch (Throwable t) {
          LOG.warn("Error closing session", t);
        }
        sessionState = null;
      }
      if (sessionHive != null) {
        try {
          Hive.closeCurrent();
        } catch (Throwable t) {
          LOG.warn("Error closing sessionHive", t);
        }
        sessionHive = null;
      }
      release(true, false);
  }

从这里可以看到Session通过迭代将所有的操作逐渐关闭,并清除Session相关日志、关闭任务历史日志流。

3.3. [Hive JDBC]:thrift server方式访问Hive

  1. 访问主类:org.apache.hive.jdbc.HiveDriver
  2. 通过ctrl+c方式断开/异常断开
      对于Hive JDBC这种连接方式而言,不存在ctrl+c直接断开RPC连接这种说法。我们通过程序测试的话,ctrl+c直接退出或kill的是我们的程序[JVM],断开程序之后session连接自然断开。
      这里的处理方式如Beeline类似,同样是HiveServer2通过session来管理任务的退出。

4. 问题是否解决

通过以上分析可以得出结论:
1. Hive Cli模式下,直接Kill -9结束当前的Hive进程,是无法让运行在Yarn上的任务退出;
2. 使用Beeline或JDBC连接Hive时,可以设置hive.server2.close.session.on.disconnect=false,来阻止session的关闭操作[未测试];

  我们基本获知了Hive通过几种方式访问集群资源时,访问的方式、驱动主类、程序退出资源释放的流程等内容。因此,以上的分析基本上解答了我们的问题。即除了Hive CLI方式通过[Kill -9]直接退出JVM之外,其他情况基本上都会停止Yarn任务的运行。

<think>好的,我现在需要帮助用户解决如何在Hive 4.0.0中关闭查询结果中的表头显示。用户之前已经询问过类似的问题,我的回答中提到了几种方法,包括设置表属性、查询时过滤、配置输出结果等。现在用户明确说他们想关闭查询结果的表头显示,所以需要进步明确具体该怎么做。 首先,我需要回顾之前的回答。在之前的回答中,第三部分提到可以通过配置`hive.cli.print.header=false`来临时关闭当前会话的表头显示。用户现在可能希望得到个更详细的步骤,或者永久性的配置方法。 接下来,查看用户提供的引用内容。引用[3]提到在hive-site.xml中配置`hive.cli.print.header`为true,这说明用户可能已经了解如何通过修改配置文件来调整这设置。因此,用户现在需要的是如何将其设置为false来关闭表头。 需要注意的是,用户可能是在使用Hive CLI或者Beeline等客户端工具时遇到表头显示的问题。不同的客户端可能有不同的配置方式。例如,Beeline默认会显示表头,而Hive CLI可能需要单独配置。 另外,用户提到的Hive版本是4.0.0,需要确认该版本中相关配置是否仍然有效。根据之前的回答中的引用[2],Hive 4.0.0在元数据存储服务方面有些配置变化,但`hive.cli.print.header`这个参数应该还是存在的,因为引用[3]提到了该配置。 用户可能的需求场景是在执行查询时,结果不显示字段名,这样在导出数据或批量处理时更方便。可能的解决方法包括临时会话设置、永久配置文件修改,或者在启动Hive时自动加载配置。 需要区分临时和永久配置。临时配置适用于单次会话,而修改hive-site.xml则是永久性的,会影响所有后续会话。用户可能需要根据具体情况选择合适的方法。 另外,用户可能对如何验证配置是否生效有疑问,需要指导他们执行个测试查询,观察输出是否有表头。如果用户使用的是Beeline,可能还需要额外的参数,如`--showHeader=false`。 最后,确保回答结构清晰,分点说明不同方法,并引用相关的引用资料,如引用[3]中的配置示例,但需要将值改为false。同时,提醒用户注意配置的位置和权限问题,如修改hive-site.xml需要相应的访问权限,可能需管理员操作。</think>在Hive 4.0.0中关闭查询结果表头显示,可通过以下两种方式实现: --- ### 、临时会话配置(推荐) 在Hive CLI或Beeline会话中直接设置参数,**仅对当前会话生效**: ```sql SET hive.cli.print.header=false; -- 关闭结果表头显示 SET hive.cli.print.current.db=false; -- 可选:同时关闭当前数据库名显示 ``` - **验证效果**: ```sql SELECT * FROM your_table LIMIT 5; -- 返回结果无表头 ``` --- ### 二、永久全局配置 修改Hive配置文件`hive-site.xml`,**对所有会话生效**(需Hive服务端权限): 1. 编辑配置文件: ```bash vi $HIVE_HOME/conf/hive-site.xml ``` 2. 添加以下配置项: ```xml <property> <name>hive.cli.print.header</name> <value>false</value> <description>关闭查询结果表头显示</description> </property> ``` 3. **重启Hive服务**使配置生效: ```bash hive --service metastore & # 重启元数据服务 hive --service hiveserver2 & # 重启HiveServer2 ``` --- ### 三、Beeline客户端专属配置 若使用Beeline连接Hive,可通过启动参数直接禁用表头: ```bash beeline -u jdbc:hive2://localhost:10000 \ --showHeader=false \ --outputformat=tsv2 ``` --- ### 配置原理说明 - **`hive.cli.print.header`** 控制Hive CLI/Beeline是否输出列标题,默认值为`true`[^3] - **版本兼容性** 该配置在Hive 4.0.0中仍有效,且适用于所有文件格式(包括ORC/Parquet) --- ### 常见问题排查 1. **配置未生效** 检查配置文件路径是否为`$HIVE_HOME/conf/hive-site.xml`,并确认Hive服务已重启 2. **Beeline表头依然显示** 添加`--showHeader=false`参数覆盖全局配置 3. **仅需临时关闭** 优先使用`SET`命令,避免影响其他用户 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值