当我使用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服务器由远程云服务提供。
最佳答案
该错误消息实际上意味着“无法到达MySQL服务-也许地址/端口错误,也许由于网络限制而无法到达该地址/端口,也许服务器已关闭-享受下一阶段的调试”。
如果您的群集节点位于受限制的子网中,并且无法访问互联网(出于安全原因,这是有道理的),则Sqoop映射器将无法访问您的“远程云服务”,即结束游戏。
您将不得不尝试其他方法,例如在可以访问Internet的另一台服务器上运行Spark“本地”作业[请参见下面的代理配置]
如果,则您的群集节点可以通过 Internet代理(这在安全性上有些松懈,但毕竟那里可能没有敏感数据)可以访问Internet,则必须配置Sqoop映射器,以便它们了解代理。剧透:很复杂。我什至不知道这是否可行。
首先,您必须向您的网络管理员团队咨询有关代理本身的信息-它们是否维护HTTP代理,HTTPS代理,SOCKS代理?在哪个主机上(或哪个DNS别名掩盖了节点池)?在哪个端口上?他们是否需要用户/密码身份验证?
然后,您必须将该信息转换为Java系统属性,如Java Networking and Proxies的Java文档页面所述。
请注意,文档隐藏了许多令人尴尬的地方:
最后但并非最不重要的一点是,您必须将适当的Java属性传递给Sqoop映射器。
将Java属性传递给映射器的正确方法是覆盖(文献记载不清)Hadoop属性
mapreduce.map.java.opts
-它不在Hadoop文档中,因此除非您在寻找某事时在博客文章(例如this one)上偶然发现它否则,您将无法知道它的存在。棘手的部分是您的默认Hadoop配置(和/或Sqoop)可能已经出于自己的目的使用了
mapreduce.map.java.opts
,并且覆盖其设置可能会导致作业崩溃(例如,没有明确的-Xmx
配额,进程超出了为容器分配的YARN) ,YARN会中途杀死该容器,所有日志都会丢失)。因此,重置该变量的安全方法是检查其“默认”值,并使用您的自定义值进行报告。
Sqoop documentation指出,要将Hadoop属性传递给映射器,可以使用配置文件或命令行覆盖
-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代理,那么强制Sqoop映射器对该所有网络流量使用该代理将切断必要的集群内Hadoop通信。
[编辑] 对于无法配置为使用Internet代理的应用程序,有一个通用的解决方法:在特定节点(集群内部或外部)下载“代理”实用程序(Wikipedia上有一个列表),然后使用它为您的远程MySQL数据库打开了一种网络隧道。
从网络 Angular 来看,这是非常低效的,因为所有数据都必须通过“代理”节点(输入+输出)以及许多额外的以太网交换机进行路由。而且,在生产过程中,您必须乞求您的IT安全团队的认可。
PS:说到效率...不要忘记MySQL JDBC URL中的
useCompression=true
参数,以减少网络开销。
关于hadoop - 使用Sqoop --query将数据从MySQL导入到HBase时出错?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44455000/