YarnClient的init方法执行后无反应

原创
2021/10/27 11:28
阅读数 131

在使用YarnClient来查询Spark任务ID的时候,初始化方法执行完没有任何反应,相同的代码在自己Windows电脑上跑的好好的,找了一个Linux的机器也是可以的,但是放到容器里面就不行(这是什么鬼)。最终发现,原来成败仅在一念之间。。。

1. 主要功能
SpringBoot启动后,连接zookeeper进行选主,抢主成功的节点连接Yarn进行任务查询,如果存在RUNNING的任务,将其kill掉,并重新提交新的Spark任务。(为的是在升级或重新安装的场景,Springboot的生命周期能和yarn上面spark任务的生命周期保持“一致”)。

2. 上代码
@Slf4j
public class AppYarnClient {
    private final YarnClient client;

    public AppYarnClient() {
        client = YarnClient.createYarnClient();
        Configuration conf = new Configuration();
        conf.addResource(new Path("/opt/huawei/iss/conf/core-site.xml"), false);
        conf.addResource(new Path("/opt/huawei/iss/conf/yarn-site,xml"), false);
        client.init(conf);
        log.info("yarn client init finished...");
        client.start();
        log.info("yarn client start finished...");
    }

    public List<ApplicationId> getRunningAppIds(String appName) {
        List<ApplicationReport> applications = null;
        try {
            EnumSet<YarnApplicationState> appStates = EnumSet.noneOf(YarnApplicationState.class);
            appStates.add(YarnApplicationState.RUNNING);
            applications = client.getApplications(appStates);
        } catch (YarnException | IOException ex) {
            log.error("get yarn applications failed. ", ex);
        }
        List<ApplicationId> runningApps = new ArrayList<>();
        if (CollectionUtils.isEmpty(applications)) {
            return runningApps;
        }
        runningApps = applications.stream()
            .filter(report -> report.getName().contains(appName))
            .map(ApplicationReport::getApplicationId)
            .collect(Collectors.toList());
        return runningApps;
    }

    public boolean killApplication(ApplicationId appId) {
        try {
            client.killApplication(appId);
        } catch (YarnException | IOException ex) {
            log.error("yarn kill application of {} failed, because: ", appId.toString(), ex);
            return false;
        }
        return true;
    }

    public void killAndSubmit() {
        log.info("the yarn client will work...");
        ShellUtils shellUtils = new ShellUtils();
        List<ApplicationId> runningAppIds = getRunningAppIds("com.huawei.iss.ce.statistic.streaming.StatisticEngine");
        log.info("the running apps are {}", runningAppIds);
        if (CollectionUtils.isEmpty(runningAppIds)) {
            log.info("there are no running app!");
            shellUtils.execute(new String[] {"sh", "-x", "/opt/huawei/iss/components/ComputingEngine/setup/start.sh"});
            return;
        }
        for (ApplicationId runningAppId : runningAppIds) {
            boolean killResult = killApplication(runningAppId);
            log.info("kill app result is: {}, the appId is {}", killResult, runningAppId.toString());
        }
        log.info("exist apps have been killed, will submit again.");
        shellUtils.execute(new String[] {"sh", "-x", "/opt/huawei/iss/components/ComputingEngine/setup/start.sh"});
    }
}
3. 问题描述
在执行完yarnClient.init(conf)后,日志只打印了一句:Service: org.apache.hadoop.yarn.client.api.impl.YarnClientImpl entered state INITED,然后这个线程就结束了,没有后续,debug日志开启也没有异常打印(黑人问号???)大数据培训

我就去查看源码,发现这一句是在状态转换的时候打印的:

但是里面除了属性赋值,没有其他的操作,不会有异常抛出(继续满脸疑惑???)。这时候我继续看源码,发现会有一个创建连接的过程,入口是在创建YarnClientImpl的时候:

@Public
public static YarnClient createYarnClient() {
    YarnClient client = new YarnClientImpl();
    return client;
}
// 然后在serviceInit方法里面,这方法好像在哪见过? 哦!就是在yarnClient.init(conf)里面
protected void serviceInit(Configuration conf) throws Exception {
    ......
    if (YarnConfiguration.timelineServiceV1Enabled(conf)) {
        this.timelineV1ServiceEnabled = true;
        this.timelineDTRenewer = getTimelineDelegationTokenRenewer(conf);
        this.timelineService = TimelineUtils.buildTimelineTokenService(conf);
    }

    if (this.timelineV1ServiceEnabled || conf.getBoolean("yarn.timeline-service.generic-application-history.enabled", false)) {
       this.historyServiceEnabled = true;
       this.historyClient = AHSClient.createAHSClient();
       this.historyClient.init(conf);
    }
    ......
    super.serviceInit(conf);
}

正常执行的情况,AHSClient.createAHSClient();这一句是可以正常初始化并连接到对应yarn节点的,但是在容器里没有打印它的执行日志。
怀疑点1:容器网络配置有问题???
检查端口和主机映射,完全没毛病,况且我zookeeper都用得好好的呢(傲娇)—— 排除此怀疑。
怀疑点2:用的配置文件有问题?(core-site.xml和yarn-site.xml)
将容器里的配置文件拿出来对比客户端用到的配置文件,完全一样!!! —— 排除此怀疑。
怀疑点3:kerberos认证失败???
检查kerberos认证过程,漏掉一个文件,补上,问题还是没解决。—— 排除此怀疑。
开始怀疑人生。。。是不是错误日志被屏蔽了,没有输出来???
尝试把错误日志输出到执行脚本的控制台,然后 ClassNotFind: javax.ws.rs.ext.MessageBodyReader,在代码里搜索了一下:

这好像也莫得问题呀。。。查看打出来的jar包,emmm,少了一个jar。
依赖树打出来看一下:都是provide,难怪没有,加到容器里去,然后重启服务,牛批!!!好了。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部