一个由FAIL_ON_SYMBOL_HASH_OVERFLOW引出的Flink类加载问题

Hadoop classpath下的Jackson 和User jar内的Jackson冲突

此文章排查问题不单单指Flink,各种on YARN 集群环境都,本文都可以提供排查思路。
直接亮出报错

java.lang.NoSuchFieldError: FAIL_ON_SYMBOL_HASH_OVERFLO    
   at org.elasticsearch.common.xcontent.json.JsonXContent.<clinit>(JsonXContent.java:57)

情况是程序在IDE运行正常,打包上Yarn集群环境就报错。

排查思路

基本问题可以定位为类加载顺序出问题

  1. 在你会使用到JacksonObjectMapper.class.getProtectionDomain().getCodeSource().getLocation()类的地方打印出class加载的文件目录,查看类加载的路径是否为你想要的路径(User jar path)
  2. 当你定位到Jackson类加载路径不对像我这样file:/usr/**/hadoop/lib/jackson-databind-2.2.3.jar从hadoop classpath下加载了ObjectMapper 而不是User jar
  3. 查看程序启动时候的classpath 设置。执行yarn logs -applicationId *** 在日志中查看程序启动时候的classpath,查看User jar 是否在classpath列表中。以flink 1.9.1为例,user jar 是不会被加入到classpath中的。
  4. 解决思路,想办法把你的User jar 加入到classpath中,并且需要排在最前面,以flink为例解决方法有2种
    • 将你的User jar 加入到 flink lib下
    • 修改bin/flink脚本,将你的user jar (USER_JAR_CLASSPATH)加入到脚本最后一行, -classpath 后面
    exec $JAVA_RUN $JVM_ARGS "${log_setting[@]}" -classpath "`manglePathList "$USER_JAR_CLASSPATH:$CC_CLASSPATH:$INTERNAL_HADOOP_CLASSPATHS"`" org.apache.flink.client.cli.CliFrontend "$@"
    

写在后面我的排查过程

因为之前有看过flink的反向类加载问题,于是从flink run 脚本开始看,一直跟代码

CliFrontend#bulidProgram line 799
PackagedProgram#PackagedProgram line 221
JobWithJars#BuildUserCodeClassLoad line 142
return FlinkUserCodeClassLoaders.parentFirst(urls, parent);

可以看到代码里面写死了使用了parentFirst,根据官方文档里面描述的反向类加载,代码的意思是首先从classpath下加载Class,而不是从user。这跟我们的意愿不一样。
FLink 1.9.2 和 1.10 已经修复了这个问题 https://issues.apache.org/jira/browse/FLINK-13749

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值