Hadoop Hive UDF与外部库

时间:2015-12-23 11:48:45

标签: java hadoop hive user-agent udf

我正在尝试为Hadoop Hive编写一个UDF,它解析用户代理。以下代码在我的本地机器上工作正常,但在Hadoop上我得到了:

  

org.apache.hadoop.hive.ql.metadata.HiveException:无法执行方法public java.lang.String MyUDF .evaluate(java.lang.String)throws org.apache.hadoop.hive.ql.metadata。 MyODF类的对象MyUDF @ 64ca8bfb上的HiveException,参数{All Occupations:java.lang.String},大小为1',

代码:

import java.io.IOException;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.*;
import com.decibel.uasparser.OnlineUpdater;
import com.decibel.uasparser.UASparser;
import com.decibel.uasparser.UserAgentInfo;

public class MyUDF extends UDF {

    public String evaluate(String i) {
        UASparser parser = null;         
        parser = new UASparser(); 
        String key = "";
        OnlineUpdater update = new OnlineUpdater(parser, key);
        UserAgentInfo info = null;
        info = parser.parse(i);
        return info.getDeviceType();
    }
}

我想到的事实应该提到:

  • 我正在使用Eclipse编译“export runnable jar file”并将所需的库提取到生成的jar选项中

  • 我正在使用Hue上传这个“胖罐”文件

  • 我设法运行的最低工作示例:

    public String evaluate(String i) { return "hello" + i.toString()"; }

  • 我想这个问题就在我正在使用的那个库(从https://udger.com下载)的某处,但我不知道在哪里。

有什么建议吗?

谢谢,Michal

2 个答案:

答案 0 :(得分:1)

这可能是一些事情。最好的办法是检查日志,但这里列出了一些你可以在一分钟内查看的快速内容。

  1. jar不包含所有依赖项。我不确定eclipse如何构建一个可运行的jar,但它可能不包含所有依赖项。你可以做到

    jar tf your-udf-jar.jar

  2. 查看包含的内容。你应该看到来自com.decibel.uasparser的东西。如果没有,您必须使用适当的依赖项构建jar(通常使用maven来实现)。

    1. 不同版本的JVM。如果使用jdk8进行编译并且集群运行jdk7,它也将失败

    2. Hive版本。有时,Hive API会略有变化,足以使其不兼容。可能不是这里的情况,但请确保针对您在群集中具有的相同版本的hadoop和hive编译UDF

    3. 在致电info

    4. 后,您应始终检查parse()是否为空
    5. 看起来图书馆使用密钥,这意味着实际上从在线服务(udger.com)获取数据,因此如果没有实际密钥,它可能无法运行。更重要的是,图书馆在线更新,联系每条记录的在线服务 。这意味着,查看代码,它将为每条记录创建一个更新线程。您应该更改代码,只在构造函数中执行一次,如下所示:

    6. 以下是如何更改它:

      public class MyUDF extends UDF {
        UASparser parser = new UASparser();
      
        public MyUDF() {
          super()
          String key = "PUT YOUR KEY HERE";
          // update only once, when the UDF is instantiated
          OnlineUpdater update = new OnlineUpdater(parser, key);
        }
      
        public String evaluate(String i) {
              UserAgentInfo info = parser.parse(i);
              if(info!=null) return info.getDeviceType();
              // you want it to return null if it's unparseable
              // otherwise one bad record will stop your processing
              // with an exception
              else return null; 
          }
      }
      

      但是要确定,您必须查看日志...纱线日志,还可以查看您正在提交作业的计算机上的配置单元日志(可能在/ var / log / hive中)但这取决于你的安装。)

答案 1 :(得分:0)

这样的问题可能可以通过以下步骤解决:

  1. 覆盖方法UDF.getRequiredJars(),使其返回hdfs文件路径列表,其中的值由您将以下xxx_lib文件夹放入hdfs的位置确定。请注意,列表雾完全包含每个jar的完整hdfs路径字符串,例如hdfs://yourcluster/some_path/xxx_lib/some.jar

  2. 按照" Runnable jar文件导出向导"导出udf代码。 (选择"将所需的库复制到生成的jar旁边的子文件夹中#34;。这些步骤将导致xxx.jar和xxx.jar旁边的lib文件夹xxx_lib

  3. 根据您在步骤0中的代码将xxx.jar和文件夹xxx_lib放入您的hdfs文件系统。

  4. 使用以下方法创建一个udf:add jar $ {the-xxx.jar-hdfs-path};创建函数your-function为$} udf class的限定名称};

  5. 试试吧。我测试了它并且它可以工作