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