首先这是一篇为了hue调用sqoop任务的路上,遇到问题解决问题的文章
实话实说,我对Hue这个框架并不了解,只是遇到了这么一个问题,然后花了老大的劲才解决,感觉要记录下~
一、背景:
Hue调用Sqoop,其实是hue生成了一个oozie的任务,实际上调用sqoop的是oozie,然后oozie是先提交一个launcher到yarn上面,然后再通过launcher拉起一个sqoop的MapReduce任务,最后执行成功,听起来是不是很麻烦!
我的sqoop命令是:
(将hive的某张表导出到mysql,并且设置了--update-key id --update-mode allowinsert,会根据update-id来更新整条数据)
sqoop export --connect jdbc:mysql://127.0.0.1:3306/project --username root --password EMRroot1234 --table foo --update-key id --update-mode allowinsert --hcatalog-database default --hcatalog-table foo --num-mappers 2
二、开始操作
1、hue读取hdfs相关路径都是通过hdfs的httpFs连接的,端口是14000
所以开启hdfs的httpFs服务就好了
Hadoop HDFS 的 HttpFS:https://www.cnblogs.com/lailailai/p/4701151.html(作者:卖程序的小歪)
2、hue上执行,基本看不到状态,这好像是hue有bug,执行完,可以到oozie的UI页面上看下,记得点击(左上角)刷新!
如果这个任务有Error,很可能任务都没提交到yarn上
我们也可以在Job Definition看到hue帮我们生成的workflow是什么样的
这个报错,是oozie.service.WorkflowAppService.system.libpath这个目录没有被创建,这应该是个hdfs的目录
这个目录是oozie运行作业系统的jar包,也就是说后续所有什么类不存在,就把jar包往这个目录下放就行
具体操作就是:
(1)、找到对应版本的sharelib,oozie-sharelib-5.1.0.tar.gz
(2)、切换到oozie用户
(3)、执行命令生成共享库 oozie-setup.sh sharelib create -fs hdfs://xxx:8020 -locallib /lib/oozie-current/oozie-sharelib-5.1.0.tar.gz
/user/oozie/share/lib,执行完命令,确认下他把lib生成到哪里了
(4)、重启oozie,使用ooize可能还会存在缺少jar的报错,可以将hive的所有jar put到生成的目录下
3、运行起来,到yarn上面看,oozie的launcher失败了,点进去看详情日志(前提是集群有开hdfs的日志聚合服务)
oozie执行sqoop命令,一些基础的指令是没有问题的,但是在用到一些特定的东西的时候,就会出问题,各种类找不到
这里的报错,是没有mysql的jar包,然后你把mysql的jar包加进去之后,还很有可能会有各式各样的jar包缺失,所以我索性就把hive的lib下面的所有jar包都放到了
oozie.service.WorkflowAppService.system.libpath这个路径下!
我的路径上默认有4个jar包
然后在hive的lib目录下执行:hdfs dfs -put *.jar /user/oozie/share/lib/lib_20210106162439/sqoop
4、然后重点就来了!
报了个空指针!!!
这完全不知道为什么空指针,而且也基本搜索不到任何相关的东西
三、排查过程:
1、命令
我首先从命令入手,我说下我测试下来的现象
(1)、那条sqoop命令,直接执行是没问题的,能完成功能没有报错
(2)、自己写一个一模一样的sqoop任务在oozie直接运行也是报错
所以我猜测不是hue的问题,应该就是oozie的问题
(3)、我增加/减少了sqoop命令的参数
去掉--update-key id --update-mode allowinsert,可以正常运行
去掉-hcatalog-database default --hcatalog-table foo,换成--export-dir,并且指定--input-fields-terminated-by "\0001",可以正常运行
并且我搜到了一篇已经打不开的文章
文章的作者说:从sqoop导出mysql,涉及hdfs、hive、cos(腾讯云对象存储)等数据源,sqoop 1.4.6导出 hive表到 mysql,如果需要用到update-key功能(根据主key更新或插入),1.4.6版本实现上有bug,1.4.7版本已经解决。
但是其实很奇怪,我的sqoop版本就是1.4.7,理论上不会遇到这个bug
2、看源码
我下载了oozie和sqoop的源码,开始看了起来
这里我就不具体解析源码了,大家有兴趣自己搜索对应的文章看
我大概文字叙述下,oozie接收到传入的参数,对参数进行解析发现是一个sqoop类型,然后任务就提交了,接着是SqoopMain这个类,拿到这个任务开始运行,做了一堆参数解析,把我的那条命令解析成了String [],最后调用了Sqoop.main(args),也就是说oozie只做了参数的解析,最后还是通过java调用了sqoop
那么问题来了,如果oozie解析出来的命令没有任何问题,调用sqoop,出了问题,就是sqoop的问题
那么我单独使用sqoop没有问题,使用oozie调用的sqoop就有问题,所以会不会是oozie中sqoop的环境有问题呢?(因为sqoop1并不是server-client这种类型框架,所以oozie应该也是自己拥有一个sqoop的jar包,里面有相应的sqoop代码,才能生成java代码,然后跑起一个mapreduce)
终于我在oozie.service.WorkflowAppService.system.libpath路径下找到了可能的对象
因此我把他删除了,并且放上了sqoop-1.4.7.jar,重启了oozie(这里应该可以不重启,执行oozie admin -sharelibupdate应该能刷新共享库)
然后我发现报错不一样了!
然后我找到了这个类,属于哪个jar,直接从中央仓库找到了avro-1.10.1.jar,在放到共享目录中,再次重启oozie,就解决了这个问题,至此任务终于跑通
你看看这个任务是几点提交的,说明那时候我还在公司搞这个问题!!!
oozie这个框架用户应该不多,用hue来调用sqoop的场景应该也比较少见(一般hue是用来提供给数据分析人员查数据的平台,sqoop偏向数据同步,一般分析人员不太会做这种事情),所以解决了这个问题,并不能带来多大的实际意义,但是从另一个层面上来看,解决问题的思路是可以分享给大家的,特别是这种一个业务依赖了多个组件或者多个框架,如何能够精确定位到是哪个框架的问题,是非常重要的一项技能!
好了话不多说了,菜鸟一只,继续努力!!
最近疫情好像有严重了起来,中国加油!