Flink SqlClient 解析 Cos Response 失败

307 阅读1分钟

问题描述

使用 flink sqlclient 查询 cos 数据,显示 s3 接口解析 response 报错,查询 hdfs 是正常的。

测试环境:

hadoop-2.7.7
flink-1.11.0
hive-2.1.1

报错日志

ERROR com.amazonaws.services.s3.model.transform.XmlResponsesSaxParser [] - Unable to parse integer value '1' java.lang.NumberFormatException: For input string: "1" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[?:1.8.0_221] at java.lang.Integer.parseInt(Integer.java:569) ~[?:1.8.0_221] at java.lang.Integer.parseInt(Integer.java:615) ~[?:1.8.0_221] at com.amazonaws.services.s3.model.transform.XmlResponsesSaxParser.parseInt(XmlResponsesSaxParser.java:240) ~[aws-java-sdk-1.7.4.jar:?]

问题排查:

1.首先,远程 debug flink,但是发现涉及到多个 flink 模块,里面的 jar 包版本冲突较为验证,很难在报错的位置, 断点到对应的实现类(有版本冲突),因此,改为打日志的方式定位。打印日志 发现 s3 接口返回的 response xml 信息解析出来的元素值,看起来都多出来一个 \n(后来发现是多了 /n/t ) 再分析日志,异常的最顶端抛出位置是在 at org.apache.hadoop.fs.FileSystem.exists(FileSystem.java:1425) ~[hadoop-common-2.7.7.jar:?],那么 hdfs 可能也存在这个问题。

2.执行 hdfs dfs -ls s3a://${bucketName}/ 测试 hdfs 访问 cos,抛出同样的错误信息。

3.远程调试 HDFS,确定报错是因为 解析出来的元素值多了 /n/t。hadoop2.7.7 版本用的 aws-java-sdk-1.7.4.jar 的 XmlResponsesSaxParser 处理 response, 底层通过 xercesImpl-2.9.1.jar 进行 xml 解析,解析元素开始位置的时候,会把 '>' 之后的内容(/n/t)也算进去。       DEBUG 信息:

4.但是从 hadoop-2.8.0 版本开始,用的是 aws-java-sdk-s3-1.10.6.jar 的 AbstractHandler 处理 response,底层还是通过 xercesImpl-2.9.1.jar 进行 xml 解析,但是 AbstractHandler 在 startElement 的时候,把非元素值( \n\t)过滤掉了,因此 hadoop 2.8.0 版本开始,正常访问未报错。
      DEBUG 信息:

问题修复

换成 hadoop 2.8.0 或 以上版本