使用sqoop--query将数据从mysql导入hbase时出错?

new9mtju  于 2021-06-01  发布在  Hadoop
关注(0)|答案(1)|浏览(573)

当我使用sqoop将所选数据从mysql导入hbase时,如下所示:

sqoop import --connect jdbc:mysql://xx.xx.xx.xx/db_company 
--username root 
--password root 
--query 'SELECT id,name FROM basic_info WHERE $CONDITIONS LIMIT 100' 
--hbase-table sls-basic-info 
--hbase-row-key id 
--split-by id -m 1 
--column-family f

它返回错误消息:

17/06/09 16:29:59 INFO mapreduce.Job:  map 0% reduce 0%
17/06/09 16:32:09 INFO mapreduce.Job: Task Id:
attempt_1496989037668_0003_m_000000_0, Status : FAILED
Error: java.lang.RuntimeException: java.lang.RuntimeException:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. 
The driver has not received any packets from the server.
    at org.apache.sqoop.mapreduce.db.DBInputFormat.setConf(DBInputFormat.java:167)
    at org.apache.hadoop.util.ReflectionUtils.setConf(ReflectionUtils.java:76)
    at org.apache.hadoop.util.ReflectionUtils.newInstance(ReflectionUtils.java:136)
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:749)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:341)
    at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:164)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:422)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1657)
    at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:158)
Caused by: java.lang.RuntimeException:     
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

我的mysql服务器是由远程云服务提供的。

j91ykkif

j91ykkif1#

该错误消息实际上意味着“无法访问mysql服务-可能地址/端口错误,可能由于网络限制无法访问此地址/端口,可能服务器已关闭-请享受下一阶段的调试”。
如果您的集群节点位于受限制的子网络中,并且无法访问internet(出于安全原因,这是有意义的),那么sqoopMap程序无法访问您的“远程云服务”--游戏结束。
您必须尝试其他方法,例如在另一台可以访问internet的服务器上运行spark“local”作业[请参阅下面的代理配置]
如果您的群集节点可以通过internet代理访问internet(这在安全性上有点松懈,但毕竟,您可能没有敏感数据),那么您必须配置sqoopMap器,以便它们知道代理。搅局者:这很复杂。我甚至不知道这是否可行。
首先,您必须向您的网络管理团队了解代理本身——他们是否维护http代理、https代理和socks代理?在哪个主机上(或者哪个dns别名屏蔽节点池)?在哪个港口?它们是否需要用户/密码身份验证?
然后必须将这些信息转换为java系统属性,如java网络和代理的java文档页所述。
请注意,文档中隐藏了许多尴尬的地方:
您不能将http/https代理用于http/https请求以外的任何内容;这对jdbc不起作用(准确地说,它需要最新版本的java和自定义java代码—这在这里是用sqoop做不到的)
您不能将身份验证与http/https代理一起使用(准确地说,它需要定制java代码—这是您在这里不能使用sqoop的)
您可以使用socks代理进行身份验证,但它在其他地方有记录,在网络属性的黑暗角落
如果您将java配置为使用socks代理,那么所有流量都将尝试通过该代理——包括后台hadoop通信;因此,您不能将它与sqoopMap器一起使用,因为它只会断开Map器与appmaster的连接!
最后但同样重要的是,您必须将适当的java属性传递给sqoopMap器。
将java属性传递给Map器的正确方法是重写hadoop属性 mapreduce.map.java.opts --它不在hadoop文档中,所以除非你在寻找其他东西时在博客文章(比如这篇)中偶然发现它,否则你无法知道它的存在。
棘手的是,您的默认hadoop配置(和/或sqoop)可能已经使用了 mapreduce.map.java.opts 出于它们自己的目的,重写它们的设置可能会导致作业崩溃(例如,没有显式的 -Xmx 配额,过程超出分配给集装箱的Yarn,Yarn在飞行途中杀死集装箱,所有原木丢失)。
因此,重置该变量的安全方法是检查其“默认”值并在自定义值中报告该值。
sqoop文档指出,要将hadoop属性传递给Map器,可以使用配置文件或命令行重写 -D <hadoop_prop>=<value >>注意后面的空格 -D ...
最后,您的sqoop命令行看起来像

... -D "mapreduce.map.java.opts=-DsocksProxyHost=xyz.abc -DsocksProxyPort=1080 -Xmx800M -Djava.net.preferIPv4Stack=true" ...

但是在这一点上,您已经知道您注定要失败了:java可以使用现成的代理类型来进行jdbc连接的只有socks;假设您的公司确实有可用的socks代理,那么强制sqoopMap程序对所有网络流量使用该代理将切断必要的集群内hadoop通信。
[编辑]对于无法配置为使用internet代理的应用程序,有一个通用的解决方法:在特定节点(集群内部或外部)下载“代理”实用程序(wikipedia上有一个列表),并使用它打开一种到远程mysql数据库的网络隧道。
这是相当低效的,网络明智的,因为所有的数据将必须通过“代理”节点(输入+输出)加上一些额外的以太网交换机路由。在生产中玩这种肮脏的把戏之前,您必须请求it安全团队的认可。
附言:说到效率。。。别忘了 useCompression=true 参数来减少网络开销。

相关问题