本文记录我在使用flink过程中遇到的部分问题,后续遇到别的问题也在这里更新,文章长期更新。
1.内存问题导致被yarn/k8s杀掉
这种问题基本都是因为物理内存或者虚拟内存超过被yarn杀掉,可以看到如下日志:
虚拟内存超标
如果是虚拟内存超过了需要改yarn配置即可,比如设置yarn.nodemanager.vmem-check-enabled为false关闭虚拟内存检测或者增加yarn.nodemanager.vmem-pmem-ratio的值,默认为2.1,比如我上图中12*2.1=25.2G。
物理内存超标
物理内存超标首先需要检查自己代码是否会有内存泄漏。此处我是用的flink-sql,并未自己写代码,所以排除上述情况。
我产生上述情况的taskmanager内存参数如下:
-Djobmanager.memory.process.size=2g \
-Dtaskmanager.numberOfTaskSlots=2 \
-Dtaskmanager.memory.process.size=12g \
-Dtaskmanager.memory.managed.fraction=0.5 \
-Dtaskmanager.memory.jvm-overhead.fraction=0.4 \
-Dstate.backend="rocksdb" \
-Dstate.backend.incremental="true" \
我用了rocksdb做状态后端,rocksdb做状态后端会直接用物理内存,且内存不是完全按照flink分配的managed.memory大小来使用,所以需要增加overhead的内存,我这里给了0.4的比例,但是真实起作用的overhead只有1gb,具体原因参见我的另一篇博文:flink-taskmanager内存计算 。
查看内存分配详情,通过flink-ui界面找到container的dataport端口
执行如下命令:
netstat -anop | grep xxxx
top -p xxxx
例如:
可以看到设置12g,已经使用了11.6g,使用的内存还是挺高的。
通过pmap -x 394 | sort -r -n -k3 > /data/tmp/394-pmap-sorted.txt 查看内存分配信息,结果如下图:
可以看到我这里有很多接近64M的内存,由于我这里是flink读hudi数据再写hudi,hudi数据存储在hdfs上,所以就想到了linux中Glibc Thread Arena问题,这个问题会导致申请很多大约64M的内存,解决这个问题需要同时修改yarn配置和flink程序配置。
- yarn配置修改yarn.nodemanager.env-whitelist配置项目,在里边新增MALLOC_ARENA_MAX。
- flink程序配置添加如下配置:-Dcontainerized.taskmanager.env.MALLOC_ARENA_MAX="1"
修改以后重新提交程序运行,继续看pmap结果:
已经没有大片的64M左右的内存了,所以上述改动生效。
除了上述解决办法还有个简单的解决办法,就是再次增大overhead。比如我增加如下参数 -Dtaskmanager.memory.jvm-overhead.max="4gb" 再结合-Dtaskmanager.memory.jvm-overhead.fraction=0.4设置该参数将原来1g的overhead设置为4g,此时尝试再运行程序,也没有再被kill了,程序内存高峰值8.8g,离进程的最大12g还有比较大的buffer空间,至此问题解决。
2. 无限重启
这个就很有意思了,很多人都会给 application 配置yarn.application-attempts参数
比如配置为 2,但是真实运行可能会发现 yarn 会重试很多次,比如下图重试了 14 次以后被我手动 kill 了
这个参数没生效的原因是因为该参数需要配合yarn.application-attempt-failures-validity-interval参数来使用,yarn.application-attempt-failures-validity-interval参数在hadoop 源码中是-1,flink提交 application 时候 flink 会通过反射给 yarn 传过去,flink 提供的这个参数默认值是 10000 也就是 10s,这个参数意思是applicationMaster(下文简称 am) 在设置的值范围内失败,会进行一次计数,像上边重试 14 次是因为作业从启动 am 到失败时间超过 10s 了,如下图,所以就不会进行计数,所以 appempt 值一直没超过预设的 5,所以就一直重试了
知道上述问题的原因以后就可以在启动 flink 程序时候修改该参数默认值,修改为自己预估的合理的值,或者直接设置为-1,为-1 表示不论am 运行了多久只要am失败 attempt 就会加 1。
增加该参数后再次运行
可以看到配置的重试 2 次已经生效了。