本文汇总了数据开发时的常见问题。

异常诊断:

作业和执行计划的区别是什么?

  • 创建作业

    在E-MapReduce中创建作业,实际只是创建了作业如何运行的配置,该配置中包括该作业要运行的JAR包、数据的输入输出地址以及一些运行参数。该配置创建好后,给它命名即定义了一个作业。

  • 执行计划
    执行计划是将作业与集群关联起来的一个纽带:
    • 可以把多个作业组合成一个作业序列。
    • 可以为作业准备一个运行集群(或者自动创建出一个临时集群或者关联一个已存在的集群)。
    • 可以为这个作业序列设置周期执行计划,并在完成任务后自动释放集群。
    • 可以在执行记录列表上查看每一次执行的执行成功情况与日志。

如何查看作业日志?

您可以直接在EMR控制台上查看作业日志。如果您是登录到Master节点提交作业和运行脚本,则您可以根据脚本自行规划。

如何在OSS上查看日志?

  1. 在E-MapReduce数据开发的页面,找到对应的工作流实例,单击运行记录
  2. 运行记录区域,单击待查看工作流实例所在行的详情,在作业实例信息页面查看执行集群ID。
  3. 在日志保存目录OSS://mybucket/emr/spark下,查找执行集群ID目录。
  4. OSS://mybucket/emr/spark/clusterID/jobs目录下会按照作业的执行ID存放多个目录,每个目录下存放了这个作业的运行日志文件。

读写MaxCompute时,抛出java.lang.RuntimeException.Parse response failed: ‘<!DOCTYPE html>…’

问题分析:可能是MaxCompute Tunnel Endpoint填写错误。

解决方法:输入正确的MaxCompute Tunnel Endpoint。

多个ConsumerID消费同一个Topic时为什么TPS不一致?

有可能这个Topic在公测或其他环境创建过,导致某些Consumer组消费数据不一致。请将对应的Topic和ConsumerID提交工单处理。

E-MapReduce中是否可以查看作业的Worker上日志?

可以。

为什么Hive创建的外部表没有数据?

问题描述:创建完外部表后查询没有数据返回。

外部表创建语句举例如下。
CREATE EXTERNAL TABLE storage_log(content STRING) PARTITIONED BY (ds STRING)
    ROW FORMAT DELIMITED
    FIELDS TERMINATED BY '\t'
    STORED AS TEXTFILE
    LOCATION 'oss://log-12453****/your-logs/airtake/pro/storage';
查询没有数据返回。
hive> select * from storage_log;

问题分析:Hive不会自动关联指定Partitions目录。

解决方法:需要您手动指定Partitions目录。
alter table storage_log add partition(ds=123);                                                                                                                                             OK
    Time taken: 0.137 seconds
    hive> select * from storage_log;   
返回如下数据。
     OK
    abcd    123
    efgh    123

为什么Spark Streaming作业运行一段时间后无故结束?

  • 首先检查Spark版本是否是1.6之前版本,如果是的话更新Spark版本。

    Spark 1.6之前版本存在内存泄漏的BUG,此BUG会导致Container被中止掉。

  • 检查自己的代码在内存使用上有没有做好优化。

为什么Spark Streaming作业已经结束,但是E-MapReduce控制台显示作业还处于“运行中”状态?

问题分析:Spark Streaming作业的运行模式是Yarn-Client。

解决方法:因为E-MapReduce对Yarn-Client模式的Spark Streaming作业的状态监控存在问题,所以请修改为Yarn-Cluster模式。

“Error: Could not find or load main class”

检查作业配置中作业JAR包的路径协议头是否是ossref,如果不是请改为ossref

如何在MR作业中使用本地共享库?

您可以在阿里云E-MapReduce控制台,YARN服务的配置页面,修改mapred-site.xml页签如下参数。
<property>  
    <name>mapred.child.java.opts</name>  
    <value>-Xmx1024m -Djava.library.path=/usr/local/share/</value>  
  </property>  
  <property>  
    <name>mapreduce.admin.user.env</name>  
    <value>LD_LIBRARY_PATH=$HADOOP_COMMON_HOME/lib/native:/usr/local/lib</value>  
  </property>

如何在MR或Spark作业中指定OSS数据源文件路径?

您可以在作业中指定输入输出数据源时使用OSS URL: oss://[accessKeyId:accessKeySecret@]bucket[.endpoint]/object/path形式,类似hdfs://

您在操作OSS数据时:
  • (建议)E-MapReduce提供了MetaService服务,支持免AccessKey访问OSS数据,直接写oss://bucket/object/path
  • (不建议)可以将AccessKey ID,AccessKey Secret以及Endpoint配置到Configuration(Spark作业是SparkConf,MR作业是Configuration)中,也可以在URI中直接指定AccessKey ID、AccessKey Secret以及Endpoint。详情请参见开发准备

Spark SQL报错“Exception in thread “main” java.sql.SQLException: No suitable driver found for jdbc:mysql:xxx”

问题分析:mysql-connector-java版本过低。

解决方法:更新mysql-connector-java至最新版本。

Spark SQL连RDS出现“Invalid authorization specification, message from server: ip not in whitelist”

检查RDS的白名单设置,将集群机器的内网地址添加到RDS的白名单中。

Hive或Impala作业读取SparkSQL导入的Parquet表报错(表包含Decimal格式的列)“Failed with exception java.io.IOException:org.apache.parquet.io.ParquetDecodingException: Can not read value at 0 in block -1 in file hdfs://…/…/part-00000-xxx.snappy.parquet”

由于Hive和SparkSQL在Decimal类型上使用了不同的转换方式写入Parquet,导致Hive无法正确读取SparkSQL导入的数据。对于已有的使用SparkSQL导入的数据,如果有被Hive或Impala使用的需求,建议加上spark.sql.parquet.writeLegacyFormat=true重新导入数据。

Beeline如何访问Kerberos安全集群?

  • HA集群(Discovery模式)
    
    !connect jdbc:hive2://emr-header-1:2181,emr-header-2:2181,emr-header-3:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2;principal=hive/_HOST@EMR.${clusterId).COM
  • HA集群
    • 连接emr-header-1
      !connect jdbc:hive2://emr-header-1:10000/;principal=hive/emr-header-1@EMR.${clusterId}.COM
    • 连接emr-header-2
      !connect jdbc:hive2://emr-header-2:10000/;principal=hive/emr-header-2@EMR.${clusterId}.COM
  • 非HA集群
    !connect jdbc:hive2://emr-header-1:10000/;principal=hive/emr-header-1@EMR.${clusterId}.COM

ThriftServer进程正常,但链接出现异常,报错 “Connection refused telnet emr-header-1 10001” 无法连接

您可以查看/mnt/disk1/log/spark日志。该问题是由于thrift server oom需要扩大内存,因此调大spark.driver.memory的值即可。

如何查看E-MapReduce服务的日志?

登录Master节点在/mnt/disk1/log中查看对应服务的日志。

Spark作业报错 "Container killed by YARN for exceeding memory limits." 或者MR作业报错 "Container is running beyond physical memory limits."

问题分析:提交App时申请的内存量较低,但JVM启动占用了更多的内存,超过了自身的申请量,导致被NodeManager异常终止。特别是Spark类型作业,可能会占用多的堆外内存,很容易被异常终止。

解决方法:
  • Spark作业,在阿里云E-MapReduce控制台,YARN服务的配置页面,调大spark.yarn.driver.memoryOverheadspark.yarn.executor.memoryOverhead的值。
  • MapReduce作业,在阿里云E-MapReduce控制台,YARN服务的配置页面,调大mapreduce.map.memory.mbmapreduce.reduce.memory.mb的值。

"Error: Java heap space"

问题分析:作业Task处理的数据量较大,但Task JVM申请的内存量不足从而抛出OutOfMemoryError。

解决方法:

"No space left on device"

问题分析:
  • Master或Worker节点空间不足,导致作业失败。
  • 磁盘空间满导致本地Hive元数据库(MySQL Server)异常,Hive Metastore连接报错。

解决方法:清理Master节点磁盘空间、系统盘的空间以及HDFS空间。

访问OSS或LogService时报错ConnectTimeoutException或ConnectionException

问题分析:OSS Endpoint需要配置为公网地址,但EMR Worker节点并无公网IP,所以无法访问。

解决方法:
  • 修改OSS Endpoint地址修为内网地址。
  • 使用EMR metaservice功能,不指定Endpoint。
例如select * from tbl limit 10可以正常运行,但是执行Hive SQL: select count(1) from tbl 时报错。修改OSS Endpoint地址为内网地址。
alter table tbl set location "oss://bucket.oss-cn-hangzhou-internal.aliyuncs.com/xxx"
alter table tbl partition (pt = 'xxxx-xx-xx') set location "oss://bucket.oss-cn-hangzhou-internal.aliyuncs.com/xxx"

读取Snappy文件时报错OutOfMemoryError

问题分析:LogService等服务写入的标准Snappy文件和Hadoop的Snappy文件格式不同,EMR默认处理的是Hadoop修改过的Snappy格式,处理标准格式时会抛出OutOfMemoryError。

解决方法,在阿里云E-MapReduce控制台,相应服务的配置页面,配置如下:
  • Hive作业:配置set io.compression.codec.snappy.native=true
  • MR作业:配置Dio.compression.codec.snappy.native=true
  • Spark作业:配置spark.hadoop.io.compression.codec.snappy.native=true

"Exception in thread main java.lang.RuntimeException: java.lang.ClassNotFoundException: Class com.aliyun.fs.oss.nat.NativeOssFileSystem not found”

在Spark作业中读写OSS数据时,需要安装E-MapReduce SDK,详情请参见准备工作

Spark接收Flume数据时为什么出现内存超用?

检查接收数据方式是否是Push-based。如果不是,请修改为Push-based方式接收数据,详情请参见Spark Streaming + Flume Integration Guide

"Caused by: java.io.IOException: Input stream cannot be reset as 5242880 bytes have been written, exceeding the available buffer size of 524288"

(OSS)网络连接重试时缓存不足,请使用1.1.0版本以上的aliyun-java-sdk-emr包。

Spark中使用OSS SDK出现 "java.lang.NoSuchMethodError:org.apache.http.conn.ssl.SSLConnetionSocketFactory.init(Ljavax/net/ssl/SSLContext;Ljavax/net/ssl/HostnameVerifier)"

因为OSS SDK与Spark和Hadoop的运行环境存在版本依赖冲突,所以不建议在代码中使用OSS SDK。

"java.lang.IllegalArgumentException: Wrong FS: oss://xxxxx, expected: hdfs://ip:9000"

因为在操作OSS数据时,使用HDFS的默认fs,所以在初始化时,需要使用OSS的路径来初始化fs,以便于使用fs来操作OSS源上的数据。
Path outputPath = new Path(EMapReduceOSSUtil.buildOSSCompleteUri("oss://bucket/path", conf));
org.apache.hadoop.fs.FileSystem fs = org.apache.hadoop.fs.FileSystem.get(outputPath.toUri(), conf);        
if (fs.exists(outputPath)) {
  fs.delete(outputPath, true);        
}

如何清理已经完成作业的日志数据?

问题描述:集群的HDFS容量被写满,发现/spark-history下有大量的数据。

解决方法:
  1. 在Spark配置页面的服务配置区域,查看是否有spark_history_fs_cleaner_enabled参数:
    • 是:修改参数值为true,可以周期性清理已经完成的作业的日志数据。
    • 否:在spark-defaults页签下,单击自定义配置,新增spark_history_fs_cleaner_enabledtrue
  2. 单击右上角的操作 > 重启 All Components
  3. 执行集群操作对话框,输入执行原因,单击确定
  4. 在弹出的确认对话框中,单击确定

为什么作业运行较慢?

问题分析:作业的JVM Heap Size设置过小,可能会引起长时间的GC,影响作业性能。

解决方法:
  • Tez:在阿里云E-MapReduce控制台,Tea服务的配置页面,可以调大Hive参数hive.tez.java.opts的值。
  • Spark:在阿里云E-MapReduce控制台,YARN服务的配置页面,可以调大spark.executor.memoryspark.driver.memory的值。
  • Mapreduce:在阿里云E-MapReduce控制台,YARN服务的配置页面,可以调大mapreduce.map.java.opts或mapreduce.reduce.java.optsmapreduce.map.java.opts或mapreduce.reduce.java.opts的值。

为什么AppMaster调度启动Task的时间过长?

问题分析:作业Task数目过多或Spark Executor数目过多,导致AppMaster调度启动Task的时间过长,单个Task运行时间较短,作业调度的Overhead较大。

解决方法:
  • 减少Task数目,使用CombinedInputFormat。
  • 提高前序作业产出数据的Block Size(dfs.blocksize)。
  • 提高mapreduce.input.fileinputformat.split.maxsize
  • 对于Spark作业,在阿里云E-MapReduce控制台,Spark服务的配置页面,调节spark.executor.instances减少Executor数目,或者调节spark.default.parallelism降低并发数。

Spark作业报错 "java.lang.IllegalArgumentException: Size exceeds Integer.MAX_VALUE"

在Shuffle时,Partition数量过少使得Block Size超过Integer.MAX_VALUE最大值。您可以尝试增大Partition数目,在阿里云E-MapReduce控制台,YARN服务的配置页面,调大spark.default.parallelismspark.sql.shuffle.partitions,或者在Shuffle前执行Repartition。

E-MapReduce是否提供实时计算的功能?

E-MapReduce提供Spark Streaming、Storm和Flink三种实时计算服务。

导入RDS数据至EMR时,时间字段显示延迟8小时如何处理?

问题描述:
  1. 例如,在云数据库RDS数据源中,数据表Test_Table中包含时间戳(TIMESTAMP)字段。data source
  2. 您可以执行以下命令,导入Test_Table中的数据至HDFS。
    sqoop import \
    --connect jdbc:mysql://rm-2ze****341.mysql.rds.aliyuncs.com:3306/s***o_sqoopp_db \
    --username s***o \
    --password ****** \
    --table play_evolutions \
    --target-dir /user/hadoop/output \
    --delete-target-dir \
    --direct \
    --split-by id \
    --fields-terminated-by '|' \
    -m 1
  3. 查询导入结果。

    查询结果显示,源数据的时间字段显示延迟8小时。

解决方法:在使用TIMESTAMP字段导入数据至HDFS时,请删除--direct参数。
sqoop import \
--connect jdbc:mysql://rm-2ze****341.mysql.rds.aliyuncs.com:3306/s***o_sqoopp_db \
--username s***o \
--password ****** \
--table play_evolutions \
--target-dir /user/hadoop/output \
--delete-target-dir \
--split-by id \
--fields-terminated-by '|' \
-m 1
查询结果显示正常。Result

如何修改Spark服务的spark-env配置?

登录集群的Header节点,修改/etc/ecm/spark-conf/spark-env.sh/var/lib/ecm-agent/cache/ecm/service/SPARK/<版本号>/package/templates/spark-env.sh中的配置。
说明 如果您在Worker节点提交任务,则需要同步修改Worker节点相关配置。

作业参数传递至脚本文件该如何处理?

在Hive作业中,您可以通过-hivevar选项,传递作业中配置的参至脚本中。
  1. 准备脚本文件。
    脚本文件中引用变量的方式为${varname}(例如${rating})。本示例中脚本的相关信息如下:
    • 脚本名称:hivesql.hive
    • 脚本的OSS路径:oss://bucket_name/path/to/hivesql.hive
    • 脚本内容
      use default;
       drop table demo;
       create table demo (userid int, username string, rating int);
       insert into demo values(100,"john",3),(200,"tom",4);
       select * from demo where rating=${rating};
  2. 登录阿里云E-MapReduce控制台
  3. 在顶部菜单栏处,根据实际情况选择地域(Region)和资源组
  4. 单击上方的数据开发页签。
  5. 项目列表页面,单击对应项目所在行的作业编辑
  6. 作业编辑区域,右键单击需要操作的文件夹,选择新建作业
  7. 输入作业名称作业描述,选择Hive作业类型。
  8. 配置作业。
    1. 基础设置页面,设置参数的KeyValue,其中Key为脚本文件中的变量名,必须与脚本一致,例如ratingconfig_parameter
    2. 作业内容中必须添加-hivevar选项,以便传递作业中配置的参数值至脚本变量。
      -hivevar rating=${rating} -f ossref://bucket_name/path/to/hivesql.hive
  9. 执行作业。
    本示例执行结果如下。submit_log

如何设置HiveServer2的认证方式为LDAP?

  1. 登录阿里云E-MapReduce控制台
  2. 在顶部菜单栏处,根据实际情况选择地域(Region)和资源组
  3. 单击上方的集群管理页签。
  4. 集群管理页面,单击相应集群所在行的详情
  5. 在左侧导航栏,单击集群服务 > Hive
  6. 新增LDAP认证配置项并重启HiveServer2。
    1. 单击配置页签,在服务配置区域单击hiveserver2-sitehiveserver2-site配置页面
    2. 单击自定义配置
      LDAP认证方式需要新增如下三个配置项。
      配置项 描述
      hive.server2.authentication LDAP 认证方式。
      hive.server2.authentication.ldap.url 格式为ldap://${emr-header-1-hostname}:10389 ${emr-header-1-hostname}是您实际的主机名称,您可以在集群的emr-header-1上执行hostname命令获取,连接主机的步骤请参见使用SSH连接主节点
      hive.server2.authentication.ldap.baseDN ou=people,o=emr
    3. 完成上述参数配置后,单击右上方的保存
    4. 确认修改对话框中,配置各项参数,单击确定
    5. 单击右上方的操作 > 重启 HiveServer2
    6. 执行集群操作对话框中,配置各项参数,单击确定
    7. 确认对话框中,单击确定
  7. 在LDAP中添加账号。

    在E-MapReduce集群中,OpenLDAP组件是LDAP的服务,默认用于管理Knox的用户账号,HiveServer2的LDAP认证方式可以复用Knox的账号体系。添加账号的方法请参见用户管理

    本示例新增账号为emr-guest

  8. 测试新增账号是否可以正常登录HiveServer2。
    通过/usr/lib/hive-current/bin/beeline登录HiveServer2,正常登录情况如下。
    beeline> !connect jdbc:hive2://emr-header-1:10000/
    Enter username for jdbc:hive2://emr-header-1:10000/: emr-guest
    Enter password for jdbc:hive2://emr-header-1:10000/: emr-guest-pwd
    Transaction isolation: TRANSACTION_REPEATABLE_READ
    如果账号密码不正确,则会显示如下异常。
    Error: Could not open client transport with JDBC Uri: jdbc:hive2://emr-header-1:10000/: Peer indicated failure: Error validating the login (state=08S01,code=0)

如何使用阿里云E-MapReduce HDFS的Balancer功能以及参数调优?

  1. 登录待配置集群任意节点。
  2. 执行以下命令,切换到hdfs用户并执行Balancer参数。
    su hdfs
    /usr/lib/hadoop-current/sbin/start-balancer.sh -threshold 10
  3. 执行以下命令,查看Balancer运行情况:
    • 方式一
      less /var/log/hadoop-hdfs/hadoop-hdfs-balancer-emr-header-xx.cluster-xxx.log
    • 方式二
      tailf /var/log/hadoop-hdfs/hadoop-hdfs-balancer-emr-header-xx.cluster-xxx.log
    说明 当提示信息包含Successfully字样时,表示执行成功。
    Balancer的主要参数。
    参数 说明
    Threshold

    默认值为10%,表示上下浮动10%。

    当集群总使用率较高时,需要调小Threshold,避免阈值过高。

    当集群新增节点较多时,您可以适当增加Threshold,使数据从高使用率节点移向低使用率节点。

    dfs.datanode.balance.max.concurrent.moves

    默认值为5。

    指定DataNode节点并发移动的最大个数。通常考虑和磁盘数匹配,推荐在DataNode端设置为4 * 磁盘数作为上限,可以使用Balancer的值进行调节。

    例如:一个DataNode有28块盘,在Balancer端设置为28,DataNode端设置为28*4。具体使用时根据集群负载适当调整。在负载较低时,增加concurrent数;在负载较高时,减少concurrent数。
    说明 DataNode端需要重启来刷新配置。
    dfs.balancer.dispatcherThreads Balancer在移动Block之前,每次迭代时查询出一个Block列表,分发给Mover线程使用。
    说明 dispatcherThreads是该分发线程的个数,默认为200。
    dfs.balancer.rpc.per.sec 默认值为20,即每秒发送的rpc数量为20。

    因为分发线程调用大量getBlocks的rpc查询,所以为了避免NameNode由于分发线程压力过大,需要控制分发线程rpc的发送速度。

    例如,您可以在负载高的集群调整参数值,减小10或者5,对整体移动进度不会产生特别大的影响。

    dfs.balancer.getBlocks.size Balancer会在移动Block前,每次迭代时查询出一个Block列表,给Mover线程使用,默认Block列表中Block的大小为2GB。因为getBlocks过程会对RPC进行加锁,所以您可以根据NameNode压力进行调整。
    dfs.balancer.moverThreads 默认值为1000。

    Balancer处理移动Block的线程数,每个Block移动时会使用一个线程。

    dfs.namenode.balancer.request.standby 默认值为false。

    Balancer是否在Standby NameNode上查询要移动的Block。因为此类查询会对NameNode加锁,导致写文件时间较长,所以HA集群开启后只会在Standby NameNode上进行查询。

    dfs.balancer.getBlocks.min-block-size Balancer查询需要移动的参数时,对于较小Block(默认10 MB)移动效率较低,可以通过此参数过滤较小的Block,增加查询效率。
    dfs.balancer.max-iteration-time 默认值为1200000,单位毫秒。

    Balancer一次迭代的最长时间,超过后将进入下一次迭代。

    dfs.balancer.block-move.timeout 默认值为0,单位毫秒。

    Balancer在移动Block时,会出现由于个别数据块没有完成而导致迭代较长的情况,您可以通过此参数对移动长尾进行控制。

    DataNode的主要参数。
    参数 说明
    dfs.datanode.balance.bandwidthPerSec 默认值为1 MB/s。

    指定DataNode用于Balancer的带宽,通常推荐设置为100 MB/s,也可以通过dfsadmin -setBalancerBandwidth 参数进行适当调整,无需重启DataNode。

    例如,在负载低时,增加Balancer的带宽。在负载高时,减少Balancer的带宽。

    dfs.datanode.balance.max.concurrent.moves 指定DataNode上同时用于Balancer待移动Block的最大线程个数。

如何使用standlone模式提交Spark任务?

E-MapReduce默认使用Spark on Yarn模式,暂不支持standlone模式。

如果E-MapReduce控制台上没有自定义配置选项,该如何处理?

  1. 登录集群的Master节点,详情请参见使用SSH连接主节点
  2. 进入配置模板的目录。
    cd /var/lib/ecm-agent/cache/ecm/service/HUE/4.4.0.3.1/package/templates/
    hue templates
    本示例以HUE为例:
    • HUE表示服务的目录。
    • 4.4.0.3.1为Hue的版本。
    • hue.ini为配置文件。
  3. 执行以下命令,添加您需要的配置。
    vim hue.ini

    当配置项已存在时,您可以根据时间情况修改参数值。

  4. 在E-MapReduce控制台,重启服务以生效配置。