无法使用 java 连接到 AWS EMR 上的配置单元
Not able to connect to hive on AWS EMR using java
我已经用 Hive 设置了 AWS EMR 集群。我想使用 java 从我的本地机器连接到 hive thrift 服务器。我尝试了以下代码-
Class.forName("com.amazon.hive.jdbc3.HS2Driver");
con = DriverManager.getConnection("jdbc:hive2://ec2XXXX.compute-1.amazonaws.com:10000/default","hadoop", "");
http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/HiveJDBCDriver.html.As 在开发者指南中提到,将与 hive jdbc 驱动程序相关的 jar 添加到 class 路径。
但是我在尝试建立连接时遇到异常。
我能够使用上面的代码(使用不同的 jdbc 驱动程序)连接到简单 hadoop 集群上的配置单元服务器。
如果我遗漏了什么,有人可以建议吗?
是否可以使用配置单元从本地计算机连接到 AWS EMR 上的配置单元服务器 jdbc?
(来自评论的合并答案)
Hive 运行 在端口 10000 上,但仅在本地,您必须创建到 emr 的 ssh 隧道。
以下来自documentation for hive 0.13.1
创建隧道
ssh -o ServerAliveInterval=10 -i path-to-key-file -N -L 10000:localhost:10000 hadoop@master-public-dns-name
连接到 JDBC
jdbc:hive2://localhost:10000/default
您可以使用库 JSch 中的代码
public static void portForwardForHive() {
try {
if(session != null && session.isConnected()) {
return;
}
JSch jsch = new JSch();
jsch.addIdentity(PATH_TO_SSH_KEY_PEM);
String host = REMOTE_HOST;
session = jsch.getSession(USER, host, 22);
// username and password will be given via UserInfo interface.
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.connect();
int assingedPort = session.setPortForwardingL(LPORT, RHOST, RPORT);
System.out.println("Port forwarding done for the post : " + assingedPort);
} catch (Exception e) {
System.out.println(e);
}
}
不确定您是否已经解决了这个问题,但它是 EMR 中的一个错误,这让我很头疼。
对于像您正在做的直接 jdbc 连接,您必须在阴影 uber-jar 中包含 jdbc 驱动程序。对于 jdbc 从数据帧内访问,您无法访问 uber-jar 中的 jar(另一个不相关的错误),但您必须在命令行中指定它(S3 是保存它们的方便位置):
--文件 s3://mybucketJAR/postgresql-9.4-1201.jdbc4.jar
但是,即使在这之后,如果您专门尝试访问配置单元,您将 运行 陷入另一个问题。 Amazon 构建了自己的 jdbc 驱动程序,与普通的 Hive 驱动程序(com.amazon.hive.jdbc41.HS2Driver)具有不同的 class 层次结构,但是 EMR 集群包含标准的 Hive jdbc 标准路径中的驱动程序 (org.apache.hive.jdbc.HiveDriver)。
这会自动注册为能够处理 jdbc:hive 和 jdbc:hive2 url,因此当您尝试连接到配置单元 URL 时,它会首先找到这个并使用它——即使你专门注册了亚马逊的。不幸的是,这个与亚马逊的 Hive EMR 版本不兼容。
有两种可能的解决方案:
1:找到有问题的驱动程序并注销它:
Scala 示例:
val jdbcDrv = Collections.list(DriverManager.getDrivers)
for(i <- 0 until jdbcDrv.size) {
val drv = jdbcDrv.get(i)
val drvName = drv.getClass.getName
if(drvName == "org.apache.hive.jdbc.HiveDriver") {
log.info(s"Deregistering JDBC Driver: ${drvName}")
DriverManager.deregisterDriver(drv)
}
}
或者
2:正如我后来发现的,您可以在尝试连接时将驱动程序指定为连接属性的一部分:
Scala 示例:
val hiveCredentials = new java.util.Properties
hiveCredentials.setProperty("user", hiveDBUser)
hiveCredentials.setProperty("password", hiveDBPassword)
hiveCredentials.setProperty("driver", "com.amazon.hive.jdbc41.HS2Driver")
val conn = DriverManager.getConnection(hiveDBURL, hiveCredentials)
这是一个更 "correct" 的版本,因为它应该覆盖任何预注册的处理程序,即使它们具有完全不同的 class 层次结构。
我已经用 Hive 设置了 AWS EMR 集群。我想使用 java 从我的本地机器连接到 hive thrift 服务器。我尝试了以下代码-
Class.forName("com.amazon.hive.jdbc3.HS2Driver");
con = DriverManager.getConnection("jdbc:hive2://ec2XXXX.compute-1.amazonaws.com:10000/default","hadoop", "");
http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/HiveJDBCDriver.html.As 在开发者指南中提到,将与 hive jdbc 驱动程序相关的 jar 添加到 class 路径。 但是我在尝试建立连接时遇到异常。 我能够使用上面的代码(使用不同的 jdbc 驱动程序)连接到简单 hadoop 集群上的配置单元服务器。 如果我遗漏了什么,有人可以建议吗? 是否可以使用配置单元从本地计算机连接到 AWS EMR 上的配置单元服务器 jdbc?
(来自评论的合并答案)
Hive 运行 在端口 10000 上,但仅在本地,您必须创建到 emr 的 ssh 隧道。
以下来自documentation for hive 0.13.1
创建隧道
ssh -o ServerAliveInterval=10 -i path-to-key-file -N -L 10000:localhost:10000 hadoop@master-public-dns-name
连接到 JDBC
jdbc:hive2://localhost:10000/default
您可以使用库 JSch 中的代码
public static void portForwardForHive() {
try {
if(session != null && session.isConnected()) {
return;
}
JSch jsch = new JSch();
jsch.addIdentity(PATH_TO_SSH_KEY_PEM);
String host = REMOTE_HOST;
session = jsch.getSession(USER, host, 22);
// username and password will be given via UserInfo interface.
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.connect();
int assingedPort = session.setPortForwardingL(LPORT, RHOST, RPORT);
System.out.println("Port forwarding done for the post : " + assingedPort);
} catch (Exception e) {
System.out.println(e);
}
}
不确定您是否已经解决了这个问题,但它是 EMR 中的一个错误,这让我很头疼。
对于像您正在做的直接 jdbc 连接,您必须在阴影 uber-jar 中包含 jdbc 驱动程序。对于 jdbc 从数据帧内访问,您无法访问 uber-jar 中的 jar(另一个不相关的错误),但您必须在命令行中指定它(S3 是保存它们的方便位置):
--文件 s3://mybucketJAR/postgresql-9.4-1201.jdbc4.jar
但是,即使在这之后,如果您专门尝试访问配置单元,您将 运行 陷入另一个问题。 Amazon 构建了自己的 jdbc 驱动程序,与普通的 Hive 驱动程序(com.amazon.hive.jdbc41.HS2Driver)具有不同的 class 层次结构,但是 EMR 集群包含标准的 Hive jdbc 标准路径中的驱动程序 (org.apache.hive.jdbc.HiveDriver)。
这会自动注册为能够处理 jdbc:hive 和 jdbc:hive2 url,因此当您尝试连接到配置单元 URL 时,它会首先找到这个并使用它——即使你专门注册了亚马逊的。不幸的是,这个与亚马逊的 Hive EMR 版本不兼容。
有两种可能的解决方案:
1:找到有问题的驱动程序并注销它: Scala 示例:
val jdbcDrv = Collections.list(DriverManager.getDrivers)
for(i <- 0 until jdbcDrv.size) {
val drv = jdbcDrv.get(i)
val drvName = drv.getClass.getName
if(drvName == "org.apache.hive.jdbc.HiveDriver") {
log.info(s"Deregistering JDBC Driver: ${drvName}")
DriverManager.deregisterDriver(drv)
}
}
或者 2:正如我后来发现的,您可以在尝试连接时将驱动程序指定为连接属性的一部分:
Scala 示例:
val hiveCredentials = new java.util.Properties
hiveCredentials.setProperty("user", hiveDBUser)
hiveCredentials.setProperty("password", hiveDBPassword)
hiveCredentials.setProperty("driver", "com.amazon.hive.jdbc41.HS2Driver")
val conn = DriverManager.getConnection(hiveDBURL, hiveCredentials)
这是一个更 "correct" 的版本,因为它应该覆盖任何预注册的处理程序,即使它们具有完全不同的 class 层次结构。