如何修复在 Hive 下运行的 geoip2 java 的“java.lang.NoSuchMethodError”

Posted

技术标签:

【中文标题】如何修复在 Hive 下运行的 geoip2 java 的“java.lang.NoSuchMethodError”【英文标题】:How to fix "java.lang.NoSuchMethodError" for geoip2 java running under Hive 【发布时间】:2019-05-22 16:13:50 【问题描述】:

在 Hive 2.3.4 (java 8) 下使用 geoip2 (maxmind) 作为依赖项执行 UDF 时遇到问题,相同的代码在使用 java 7 的旧版本 hive 以及使用 java 8 的 Presto 下工作正常。

我尝试过使用精确依赖项(maven)和手动编译、多个版本的 hive,将代码和依赖项减少到最低限度

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

import java.io.File;
import java.io.IOException;
import java.net.InetAddress;

import com.maxmind.geoip2.record.City;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.exception.GeoIp2Exception;

public final class CityName extends UDF 
        public String evaluate(String dbFile) throws IOException,GeoIp2Exception 
            File database = new File(dbFile);
            InetAddress ipAddress = InetAddress.getByName("127.0.0.1");
            DatabaseReader reader = new DatabaseReader.Builder(database).build();
            return "Database: "+dbFile.toString();
        

错误信息

2019-05-21T16:31:56,631 ERROR [ce3bca33-87aa-4468-b1ed-7080e95efb2d main([])]: ql.Driver (SessionState.java:printError(1126)) - FAILED: SemanticException [Error 10014]: Line 1:7 Wrong arguments ''/root/GeoIP2-City.mmdb'': org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public java.lang.String com.example.hive.udf.CityName.evaluate(java.lang.String) throws java.io.IOException,com.maxmind.geoip2.exception.GeoIp2Exception,java.net.UnknownHostException with arguments /root/GeoIP2-City.mmdb:com.maxmind.geoip2.DatabaseReader.(Lcom/maxmind/geoip2/DatabaseReader$Builder;Lcom/maxmind/geoip2/DatabaseReader$1;)V
org.apache.hadoop.hive.ql.parse.SemanticException: Line 1:7 Wrong arguments ''/root/GeoIP2-City.mmdb'': org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public java.lang.String com.example.hive.udf.CityName.evaluate(java.lang.String) throws java.io.IOException,com.maxmind.geoip2.exception.GeoIp2Exception,java.net.UnknownHostException with arguments /root/GeoIP2-City.mmdb:com.maxmind.geoip2.DatabaseReader.(Lcom/maxmind/geoip2/DatabaseReader$Builder;Lcom/maxmind/geoip2/DatabaseReader$1;)V
at org.apache.hadoop.hive.ql.parse.TypeCheckProcFactory$DefaultExprProcessor.process(TypeCheckProcFactory.java:1367)
at org.apache.hadoop.hive.ql.lib.DefaultRuleDispatcher.dispatch(DefaultRuleDispatcher.java:90)
at org.apache.hadoop.hive.ql.lib.DefaultGraphWalker.dispatchAndReturn(DefaultGraphWalker.java:105)
.......
Caused by: java.lang.NoSuchMethodError: com.maxmind.geoip2.DatabaseReader.(Lcom/maxmind/geoip2/DatabaseReader$Builder;Lcom/maxmind/geoip2/DatabaseReader$1;)V
at com.maxmind.geoip2.DatabaseReader$Builder.build(DatabaseReader.java:160)
at com.example.hive.udf.CityName.evaluate(CityName.java:20)
... 47 more

【问题讨论】:

【参考方案1】:

我们遇到了一个非常相似的问题。在我们的例子中,结果在 Hive 部署的类路径中有一个过时的 maxmind-db 版本。这甚至可能在较新版本的 Hive 上默认设置,但我尚未确认。

要解决此问题,只需遮蔽对 com.maxmind 的所有引用。此外,为了安全起见,还要隐藏对 fastxml.jackson 的任何引用——这是 GeoIP2 的核心依赖项之一,类路径中的冲突往往会导致类似这样的奇怪运行时问题。您可以在 Hive UDF GeoIP 库之一的 PR addressing such issue 中看到一个示例。

【讨论】:

以上是关于如何修复在 Hive 下运行的 geoip2 java 的“java.lang.NoSuchMethodError”的主要内容,如果未能解决你的问题,请参考以下文章

安装 GeoIP2 时出错:geoip2/geoip2 v2.3.1 需要 maxmind/web-service-common

如何从 shell 运行 hive 命令?

如何在 javascript 中设置 geoIP2?

带有 uWSGI 的 Django 中 Geoip2() 上的“[Errno 12] 无法分配内存”

如何使用 GeoIP2() django 模型从 IP 地址调用中提取保存的信息以显示在我的 html 中

如何修复异常:在 Hive serde 表中保存数据 请使用 insertInto() API 作为替代方法。火花:2.1.0