环境:
hadoop:2.6.0
hive:1.1.0
spark:1.6.0
需求及问题
需求:自定义一个udf函数,对存放在hive表里面的文章进行切词,同时切词需要使用自定义词库
(属于外部资源)问题就是在sql里面使用自定义的udf函数,会报错:
ERROR [RPC-Handler-3]: rpc.RpcDispatcher (RpcDispatcher.java:exceptionCaught(155)) - [ClientProtocol] Closing channel due to exception in pipeline.
io.netty.handler.codec.DecoderException: org.apache.hive.com.esotericsoftware.kryo.KryoException: Buffer underflow.
Serialization trace:
Caused by: org.apache.hive.com.esotericsoftware.kryo.KryoException: Buffer underflow.
Serialization trace:
ERROR [main]: status.SparkJobMonitor (RemoteSparkJobMonitor.java:startMonitor(169)) - Failed to monitor Job[0] with exception 'java.lang.IllegalStateException(RPC channel is closed.)'
java.lang.IllegalStateException: RPC channel is closed.
这个报错信息提示的是org.apache.hive.com.esotericsoftware.kryo.KryoException: Buffer underflow. 我一直以为是kyro序列化的问题,然后各种找解决方案,也没有实际的解决问题,最后我把自定义hive udf函数继承的UDF 换成GenericUDF,再次运行sql同样也会报错:
ERROR [main]: status.SparkJobMonitor (SessionState.java:printError(1124)) - Job failed with java.lang.NullPointerException
java.util.concurrent.ExecutionException: Exception thrown by job
ERROR [main]: status.SparkJobMonitor (SessionState.java:printError(1124)) - Failed to monitor Job[1] with exception 'java.lang.IllegalStateException(RPC channel is closed.)'
java.lang.IllegalStateException: RPC channel is closed.
解决方法
更换了集成的GenericUDF类就可以直接定位到问题了,我的hive udf函数代码就不粘了,可以自行百度;在代码里有一个读取本地文件的操作,而我的sql是通过hive客户端通过hive on spark运行的,这个时候再读本地文件很显然读不到,就会报错Job failed with java.lang.NullPointerException 空指针异常,从报错信息也可以直接定位到我的代码是读取本地文件报的错
定位到问题就很好解决了,这个时候直接在hive客户端中 add file 目标文件;即可正常运行; 还有一个坑就是在 add file后 hive客户端会打印:Added resources: [/home/jar/dict/CountryLeader.dict]
这表示你add的是相对路径,将文件位置作为参数传入自定义udf函数时直接:./文件名 即可;
这种情况是不能动态修改本地资源,需要动态修改本地资源,用spark代码实现,查阅资料时也发现了其他方式,不过比较麻烦;
第一次写优快云 会有很多不规范的,望理解