上文说道,我们初步的思路是通过HIve的日志和yarn的接口获取任务进度。
可能用到的其他知识:
在实际的执行过程中,我遇到一个问题:在代码中写死的yarn的接口,如果yarn的服务地址发生改变怎么办?如果面对多个不同的yarn集群怎么办?可见我们需要动态的yarn的接口地址。
如何获取yarn集群的地址?
首先需要明白的是,Hive一定知道yarn集群地址。我突然想到Hive中提供了Hook的钩子(在Hive相应的阶段,执行对应的Jar包的方法)。通过Hook我们可以在项目执行之前,获取到任务的提交的yarn集群地址。然后在通过访问我们Java客户端提供的接口,将yarn集群的地址以JSON的格式发过来。
最终思路
- Java客户端提交任务给Hive集群,Hive执行Hook钩子,将yarn集群地址发送到Java客户端的接口。
- Java客户端获取到yarn集群地址,Java客户端读取Hive的日志,获取到任务id。
- 通过yarn集群地址和任务Id,由yarn的接口获取到相应的任务进度。
编码
Java客户端读取任务进度类
public class HiveTaskProgressServer {
private HiveStatement hiveStatement;
/**
* 停止线程的标志,true代表停止
*
*/
private Boolean isStop=false;
public HiveStatement getHiveStatement() {
return hiveStatement;
}
public void setHiveStatement(HiveStatement hiveStatement) {
this.hiveStatement = hiveStatement;
}
public Boolean getStop() {
return isStop;
}
public void setStop(Boolean stop) {
isStop = stop;
}
/**
* 功能描述:
* 检索日志是否输出appId
* @author twalk
* @date 2018/12/9 11:08 PM
* @param
* @return
*/
private String updateQueryLog() {
try {
List<String> queryLogs = hiveStatement.getQueryLog();
for (String log : queryLogs) {
System.out.println("进度信息-->"+log);
// 获取appId
if(log.indexOf("Status: Running (Executing on YARN cluster with App id")>-1){
String[] strings = log.split("application");
String appId = "application"+strings[strings.length-1].split("\\)")[0];
return appId;
}
}
}
catch (Exception e) {
System.out.println(e);
}
return null;
}
/**
* 功能描述:
* 异步获取hive任务的进度
* @author twalk
* @date 2018/12/10 12:06 AM
* @param taskId
* 任务的id
* @param taskType
* 任务的类型
* @return
*/
@Async(value = "asyncServiceExecutor")
public</