1. 记一次Flink的TaskManager运行失败分析
1. 主要环境说明:
- Java8
- Hadoop3.2
- Flink 1.14.2
2.场景说明
flink集群是通过大数据平台(XSailboat)启动,运行在Yarn上的。
flink集群运行起来以后,提交Job,无法运行成功。
![](https://img.haomeiwen.com/i27700986/547a304d6969e204.png)
3.排查过程
3.1 查看JobManager的日志
![](https://img.haomeiwen.com/i27700986/99fc1e7023540fa0.png)
发现TaskManager运行在XCloud154上,运行失败。
3.2 查看Container的运行日志
日志在XCloud154的产品目录下logs/userlogs/{applicationId}/{containerId}下
![](https://img.haomeiwen.com/i27700986/40723bc2b51200e0.png)
从taskmanager.err和taskmanager.log中寻找出错原因。
在taskmanager.log中发现以下异常消息。
![](https://img.haomeiwen.com/i27700986/e54cb9c00f6e22ae.png)
从中可以发现是因为找不到flink-conf.yaml文件。
接着分析launch_container.sh文件里面的内容,发现并没有flink-conf.yaml相关的文件引入信息。正常情况下,应该有以下shell命令。
ln -sf -- "xxxxx" "flink-conf.yaml"
这说明JobManager在启动TaskManager的时候,没有引入flink-conf.yaml。
为了理解其为什么没有引入这个文件,就需要分析flink源码,理解其逻辑,才有可能找到没有引入flink-conf.yaml的原因。
3.3 flink源码分析
笔者目前并没有怎么分析过flink的源码,对flink源码并不了解。但是笔者写过Yarn Application,知道一个Yarn Application Master是如何启动一个容器,运行程序的。在当前情形下Job Mananger就是 Yarn AM,TaskManager就是其运行起来的APP。Yarn AM启动一个APP必然会用到Hadoop的一个类:
org.apache.hadoop.yarn.api.records.ContainerLaunchContext
上GitHub上的flink项目查找这个类。如果GitHub慢可以下载源码,导入到IDE中进行查找。
排除掉测试类,有可能相关的有下面几个:
- flink-yarn/src/main/java/org/apache/flink/yarn/Utils.java
- flink-yarn/src/main/java/org/apache/flink/yarn/YarnResourceManagerDriver.java
-
flink-yarn/src/main/java/org/apache/flink/yarn/YarnClusterDescriptor.java
Yarn AM启动一个APP还会用到
org.apache.hadoop.yarn.api.records.LocalResource
搜索一下,很快就发现Utils.java中的这段代码
![](https://img.haomeiwen.com/i27700986/63a9fe314d2554dc.png)
有过写Yarn App经验的,一眼就能看出来,这是构造容器中APP运行所使用的文件资源(ContainerLaunchContext,容器启动上下文)的代码。
这段代码所属方法是
![](https://img.haomeiwen.com/i27700986/6b83cf9752cd1ff4.png)
一看方法名,就确定没有找错了。
在其中寻找flink-conf.yaml配置加入其中的代码。发现并没有代码直接表明把flink-conf.yaml引入进来,那很可能就是批量添加过程中被添加进来的。
很快这段代码引起了我注意:
![](https://img.haomeiwen.com/i27700986/5d5b508bef4eee65.png)
首先它是批量添加,其次shipListString这个变量名中的ship也引起了我的关注。因为大数据平台(XSailboat)
在Yarn中启动JobManager的启动命令中,就有变量是包含"ship"这个单词的。
分析代码,看看此处shipListString是什么?
![](https://img.haomeiwen.com/i27700986/3cea6f74da8d9d60.png)
看看YarnConfigKeys.ENV_CLIENT_SHIP_FILES到底是个什么内容。
![](https://img.haomeiwen.com/i27700986/96c70d6d2ac43a1f.png)
_CLIENT_SHIP_FILES正是启动JobManager的脚本中包含的参数。
查看JobManager的启动脚本
![](https://img.haomeiwen.com/i27700986/a32d23b8b05202ed.png)
所以 decodeYarnLocalResourceDescriptorListFromString(shipListString).forEach()的功能就是把JobMananger中_CLIENT_SHIP_FILES声明的文件资源引入进来,作为TaskMananger启动上下文的一部分。
分析_CLIENT_SHIP_FILES的内容,发现是在构造过程中少了一个";"
![](https://img.haomeiwen.com/i27700986/32cdb26cce13be64.png)
修改自己写的构造_CLIENT_SHIP_FILES的代码,把“;”加上,至此问题解决了。
最后附一张我们大数据平台(XSailboat)中的DataStudio模块中开发开发实时计算管道,运行在Flink集群上的截图。
![](https://img.haomeiwen.com/i27700986/4c55639c7c35bbaa.png)
正在开发中...