张恒 发布的文章

直接运行java程序

假设我们在容器中直接启动的是我们的程序,例如java -jar xxx.jar。如果执行docker stop <container>,则意味着调用了kill -15 1

对于java程序而言,它会接收到SIGTERM信号,Runtime的ShutdownHook钩子将会被回调。像spring这样的框架,都会把自己加入到ShutdownHook回调中,在回调中执行destroy、close等生命周期操作。

所以说如果只是执行kill -15 PID命令,java程序是可以优雅的关闭。但同时我们也能看出,如果在ShutdownHook钩子中执行很耗时的操作,那么执行这个命令短时间内也不会停止java程序。所以在ShutdownHook中尽量不要做耗时长的操作,而是应该处理一些IO关闭、缓存刷新的操作。

在shell中运行java程序

假设我们在容器中启动的不是程序,而是一个shell脚本,在shell脚本中启动了一个进程。此时,
如果执行docker stop <container>,shell脚本收到SIGTERM信号后并不会把信号传给它的子进程,也就是说java程序不会做任何动作,直到宽限期到期会强制关闭容器等于kill -9。

如果对java程序执行了kill -9操作,那么java程序会直接停止运行,跳过ShutdownHook钩子回调。跳过ShutdownHook回调对java程序来说,是最不友好的操作。像spring框架,业务上我们在destroy方法上操作了很多关闭连接、回刷硬盘、回刷缓存等等结束操作,一旦执行kill -9操作,java程序中的这些资源将不会被正常释放,业务逻辑将出现bug。

解决方案

方法1

java -jar xxx.jar &
pid="$!"

_kill() {
  kill $pid
  wait $pid
  exit 0
}
trap _kill SIGTERM
wait

使用&字符将java程序后台运行,然后获取到java程序的pid。使用trap命令接收关闭信号,并指定调用kill方法。最后使用wait命令挂起shel脚本。

kill方法中,正常kill java程序并等待java程序结束。

方法2

exec java -jar xxx.jar

如果shell脚本中只启动一个java程序,那么可以使用exec命令。shell的内建命令exec将并不启动新的shell,而是用要被执行命令替换当前的shell进程,并且将老进程的环境清理掉,而且exec命令后的其它命令将不再执行。

方法3

容器启动时,在启动参数中增加--init。它的作用是在shell进程结束后,清理掉其他僵尸进程。

https://docs.docker.com/engine/reference/run/#specify-an-init-process

Hive是一个使用类SQL管理分布式存储上大规模数据集的数据仓库,它提供了命令行工具和JDBC驱动程序帮助用户使用Hive。

hive基于hadoop,它的具体功能如下:

  • 通过SQL轻松访问数据的工具,从而实现数据仓库任务,例如提取/转换/加载(ETL),报告和数据分析。
  • 一种将结构强加于各种数据格式的机制
  • 访问直接存储在Apache HDFS ™ 或其他数据存储系统(例如Apache HBase ™)中的文件
  • 通过Apache Tez ™, Apache Spark ™或 MapReduce执行查询
  • HPL-SQL的过程语言
  • 通过Hive LLAP,Apache YARN和Apache Slider进行亚秒级查询检索。

以上内容来自Apache Hive官网,hive在1.x版本中只支持MapReduce,从2.x开始开始支持其他分布式计算引擎。

- 阅读剩余部分 -