Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带有外部库的Hadoop Hive UDF_Java_Hadoop_Hive_User Agent_Udf - Fatal编程技术网

Java 带有外部库的Hadoop Hive UDF

Java 带有外部库的Hadoop Hive UDF,java,hadoop,hive,user-agent,udf,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)抛出org.apache.hadoop.hive.ql.metadata.HiveExceptionMyUDF@64ca8bfbMyUDF类

我正在尝试为Hadoop Hive编写一个UDF,用于解析用户代理。以下代码在我的本地机器上运行良好,但在Hadoop上我得到:

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

代码:

我想到的事实应该提到:

  • 我使用Eclipse编译“导出可运行的jar文件”,并将所需的库提取到生成的jar选项中

  • 我正在上传这个带有色调的“胖罐子”文件

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

    公共字符串求值(字符串i){
    返回“hello”+i.toString()”;
    }

  • 我猜问题出在我正在使用的库(下载自)的某个地方,但我不知道在哪里

有什么建议吗


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

  • jar不包含所有依赖项。我不确定eclipse如何构建可运行的jar,但它可能不包含所有依赖项。您可以这样做

    jar tf your-udf-jar.jar

  • 要查看包含的内容,您应该查看
    com.decibel.uasparser
    中的内容。如果没有,您必须使用适当的依赖项构建jar(通常使用maven)

  • 不同版本的JVM。如果使用jdk8编译,集群运行jdk7,那么它也会失败

  • 配置单元版本。有时配置单元API会发生轻微变化,足以导致不兼容。这里可能不是这样,但请确保针对集群中相同版本的hadoop和配置单元编译UDF

  • 调用
    parse()

  • 看起来库使用了一个键,这意味着它实际上从在线服务(udger.com)获取数据,因此,如果没有实际的密钥,它可能无法工作。更重要的是,库将联机更新,并与每个记录的联机服务联系。这意味着,查看代码,它将为每个记录创建一个更新线程。您应该在构造函数中更改代码,使其仅执行一次,如下所示:

  • 以下是如何更改它:

    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中,但这取决于您的安装)。

    此类问题可能可以通过以下步骤解决:

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

  • 按照“Runnable jar file exporting wizard”(选择“将所需库复制到生成的jar旁边的子文件夹中”)导出
    udf
    代码。此步骤将生成xxx.jar和xxx.jar旁边的lib文件夹xxx_lib

  • 根据步骤0中的代码,将xxx.jar和文件夹xxx_lib放入hdfs文件系统

  • 使用以下方法创建udf:添加jar${xxx.jar hdfs path};将函数创建为$}udf类的限定名}


  • 试试看。我测试了一下,它就可以工作了。

    你是否查看了
    应用程序_xxxx_xxxx
    (如Hive所报告的)的纱线日志,以检查一些线索,例如,使用比Hive使用的JRE更新的Java版本编译的JAR的一些内部异常(只是一个示例)?我们的Hadoop机器已经停机一段时间了,所以我没有机会查看日志,但是我检查了依赖项,它们似乎没有问题2)这是一个问题,是一个退步。但是,当版本不兼容时,Java会抛出一个关于错误版本的异常,而不是IOException/HiveException 3)应该可以4)我会试试这个5)它可以使用密钥(我在Hadoop外部检查).我知道效率不高,但我认为解决这个问题应该是下一步。然而,当我在图书馆里浏览时,我想到了另一个想法…它试图写入临时文件,这是UDF功能的合法操作吗(写入文件系统?HDFS是仅附加的系统,因此我在这里发现了一些问题?…谢谢,我感谢您的帮助:)UDF读取/写入本地文件是合法的,但绝对不建议这样做!但在某些情况下可以安全地完成。在以前的工作中,我们将配置文件推送到所有机器上,并使用UDF读取配置文件并将其内容提供给查询。但该库为每个记录打开网络连接。这非常有用效率高而且不好……所以是的,它闻起来有麻烦:)该库不是为hadoop设计的。在编写使用库的UDF时,您应该非常小心,看看它在内部是如何工作的。因此我发现该库还支持从文件导入该配置。但是我仍然收到“未找到文件”异常,所以我的问题是,如何找到文件的路径ded?我通过Hue上传了它,和.jar文件在同一个目录下。
    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; 
        }
    }