集群繁忙时偶发性空指针导致app执行失败

app提交上来之后,运行过程出现偶发性的空指针异常,导致连续执行两次之后,app 异常结束

放在最前面:该问题是社区已知的缺陷,更多参考:https://issues.apache.org/jira/browse/YARN-3260arrow-up-right。本文主要介绍问题定位思路和分析过程。

1. 问题描述

app执行日志中异常堆栈如下:

从字面意思理解就是AM启动之后向RM注册异常,然后失败了。

通过进一步的了解,我们知道yarn 集群最近做了扩容,app 提交规模也上来了。而且有部分app成功,有部分失败。失败app原因都是如上截图所示,没有明显的node 关联性。

2. 问题分析

2.1 确认异常位置

从异常堆栈,我们看到是AM向RM注册的过程中,抛出空指针异常导致app异常退出。也就是说不是am 本身的代码逻辑出现空指针,而是RPC调用返回了空指针。进一步说就是RM在处理过程中出现空指针。

我们通过搜索RM日志,并没有相关时间范围内发现有异常信息。

现在我们走到了一个死胡同,我们知道是RM在处理AM注册请求时出现空指针异常,但是在RM日志中找不到异常信息,而且AM异常堆栈中没有打印RM空指针出现的行号。

2.2 RM 日志分析

进一步RM日志,我们观察到一个异常信息

这个异常是说AM执行异常了,退出码为1(其实也容易理解,AM向RM注册异常,尝试几次之后,告诉RM我执行不下去了,我要异常退出)。

所以回到RM日志,我们重新梳理了RM处理AM注册部分的逻辑。

重点看如下日志(通过appid 关键字过滤)

结合下图(RMAppAttempt 状态流转图,完整图arrow-up-right),我们来分析在AM启动之后,向RM注册过程,会涉及到RMAppAttempt 对象从Allocated到running状态到变化。

我们19:14:04,023 看到日志关键字: Done launching 。说明AM已经被发送到NodeManager 。然后接下来第二行日志 (也就是19:14:09)我们看到日志关键字:AM registration 。这就是说在 14分04秒RM下发完成,14分09秒AM就来注册了。接下来神奇的事情发生了,也就是再下面第二行(也就是19:14:16)我们看到RMAppAttempt 状态变化了(change from ALLOCATED to LAUNCHED)。

我们比较一个成功的app 对应的RM处理日志,则没有上面描述的问题

这说明啥呢,说明RMAppAttempt对象还没有变launched状态,AM的注册就来了。这会导致什么问题?

问题就是yarn-3260arrow-up-right提到的,简要而言就是有如下图两个异步过程,一个过程(左边)是向缓存中添加token ,一个过程(右边)是从缓存中获取token。如果获取的过程比添加的过程要早执行,则会拿不到token。最麻烦的是获取的过程在获取返回之后,会执行编码(getEncoded)操作

如此就会出现NPE(NullPointerException)

3.解决办法

jira 提到的解决办法就是不要在allocated到launched过程去保存token ,而是把保存token 提前,放到ALLOCATED_SAVING 到allocated 到过程去,这样保存token 之后,才去拉起的AM,然后才是AM注册。

4.补充

这个问题本身比较简单,但是解决的门槛比较高,因为你得了解yarn 处理App的细节流程。最开始我们直接google ,并没有找到有用的信息(都指向yarn-site,yarn-core 的配置),直到后面我们通过在搜索前面加上 jira hadoop 关键字才看到有用信息。所以在直接google 没有什么用的时候,一定要去jira 上面看看

为什么会慢呢?无非是两个原因:1.中央异步处理器缓存队列处理比较慢,或者队列事件比较多。二. AMLaunchedTransition 处理过程慢。具体原因还要具体分析

Last updated