华为云用户手册

  • 问题 使用运行的Spark Streaming任务回写Kafka时,Kafka上接收不到回写的数据,且Kafka日志报错信息如下: 2016-03-02 17:46:19,017 | INFO | [kafka-network-thread-21005-1] | Closing socket connection to /10.91.8.208 due to invalid request: Request of length 122371301 is not valid, it is larger than the maximum size of 104857600 bytes. | kafka.network.Processor (Logging.scala:68)2016-03-02 17:46:19,155 | INFO | [kafka-network-thread-21005-2] | Closing socket connection to /10.91.8.208. | kafka.network.Processor (Logging.scala:68)2016-03-02 17:46:19,270 | INFO | [kafka-network-thread-21005-0] | Closing socket connection to /10.91.8.208 due to invalid request: Request of length 122371301 is not valid, it is larger than the maximum size of 104857600 bytes. | kafka.network.Processor (Logging.scala:68)2016-03-02 17:46:19,513 | INFO | [kafka-network-thread-21005-1] | Closing socket connection to /10.91.8.208 due to invalid request: Request of length 122371301 is not valid, it is larger than the maximum size of 104857600 bytes. | kafka.network.Processor (Logging.scala:68)2016-03-02 17:46:19,763 | INFO | [kafka-network-thread-21005-2] | Closing socket connection to /10.91.8.208 due to invalid request: Request of length 122371301 is not valid, it is larger than the maximum size of 104857600 bytes. | kafka.network.Processor (Logging.scala:68)53393 [main] INFO org.apache.hadoop.mapreduce.Job - Counters: 50
  • 回答 Spark部署时,如下jar包存放在客户端的“${SPARK_HOME}/jars/streamingClient010”目录以及服务端的“${BIGDATA_HOME}/FusionInsight_Spark2x_8.1.0.1/install/FusionInsight-Spark2x-3.1.1/spark/jars/streamingClient010”目录: kafka-clients-xxx.jar kafka_2.12-xxx.jar spark-streaming-kafka-0-10_2.12-3.1.1-hw-ei-311001-SNAPSHOT.jar spark-token-provider-kafka-0-10_2.12-3.1.1-hw-ei-311001-SNAPSHOT.jar 由于“$SPARK_HOME/jars/streamingClient010/*”默认没有添加到classpath,所以需要手动配置。 在提交应用程序运行时,在命令中添加如下参数即可,详细示例可参考编包并运行程序。 --jars $SPARK_CLIENT_HOME/jars/streamingClient010/kafka-client-2.4.0.jar,$SPARK_CLIENT_HOME/jars/streamingClient010/kafka_2.12-*.jar,$SPARK_CLIENT_HOME/jars/streamingClient010/spark-streaming-kafka-0-10_2.12-3.1.1-hw-ei-311001-SNAPSHOT.jar 用户自己开发的应用程序以及样例工程都可使用上述命令提交。 但是Spark开源社区提供的KafkaWordCount等样例程序,不仅需要添加--jars参数,还需要配置其他,否则会报“ClassNotFoundException”错误,yarn-client和yarn-cluster模式下稍有不同。 yarn-client模式下 在除--jars参数外,在客户端“spark-defaults.conf”配置文件中,将“spark.driver.extraClassPath”参数值中添加客户端依赖包路径,如“$SPARK_HOME/jars/streamingClient010/*”。 yarn-cluster模式下 除--jars参数外,还需要配置其他,有三种方法任选其一即可,具体如下: 在客户端spark-defaults.conf配置文件中,在“spark.yarn.cluster.driver.extraClassPath”参数值中添加服务端的依赖包路径,如“${BIGDATA_HOME}/FusionInsight_Spark2x_8.1.0.1/install/FusionInsight-Spark2x-3.1.1/spark/jars/streamingClient010/*”。 将各服务端节点的“original-spark-examples_2.12-3.1.1-xxx.jar”包删除。 在客户端“spark-defaults.conf”配置文件中,修改或增加配置选项“spark.driver.userClassPathFirst” = “true”。
  • 回答 如下图所示,Spark Streaming应用中定义的逻辑为,从Kafka中读取数据,执行对应处理之后,然后将结果数据回写至Kafka中。 例如:Spark Streming中定义了批次时间,如果数据传入Kafka的速率为10MB/s,而Spark Streaming中定义了每60s一个批次,回写数据总共为600MB。而Kafka中定义了接收数据的阈值大小为500MB。那么此时回写数据已超出阈值。此时,会出现上述错误。 图1 应用场景 解决措施: 方式一:推荐优化Spark Streaming应用程序中定义的批次时间,降低批次时间,可避免超过Kafka定义的阈值。一般建议以5-10秒/次为宜。 方式二:将Kafka的阈值调大,建议在FusionInsight Manager中的Kafka服务进行参数设置,将socket.request.max.bytes参数值根据应用场景,适当调整。
  • 问题 执行Spark Core应用,尝试收集大量数据到Driver端,当Driver端内存不足时,应用挂起不退出,日志内容如下。 16/04/19 15:56:22 ERROR Utils: Uncaught exception in thread task-result-getter-2java.lang.OutOfMemoryError: Java heap spaceat java.lang.reflect.Array.newArray(Native Method)at java.lang.reflect.Array.newInstance(Array.java:75)at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1671)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1707)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:71)at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:91)at org.apache.spark.scheduler.DirectTaskResult.value(TaskResult.scala:94)at org.apache.spark.scheduler.TaskResultGetter$$anon$3$$anonfun$run$1.apply$mcV$sp(TaskResultGetter.scala:66)at org.apache.spark.scheduler.TaskResultGetter$$anon$3$$anonfun$run$1.apply(TaskResultGetter.scala:57)at org.apache.spark.scheduler.TaskResultGetter$$anon$3$$anonfun$run$1.apply(TaskResultGetter.scala:57)at org.apache.spark.util.Utils$.logUncaughtExceptions(Utils.scala:1716)at org.apache.spark.scheduler.TaskResultGetter$$anon$3.run(TaskResultGetter.scala:56)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)Exception in thread "task-result-getter-2" java.lang.OutOfMemoryError: Java heap spaceat java.lang.reflect.Array.newArray(Native Method)at java.lang.reflect.Array.newInstance(Array.java:75)at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1671)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2000)at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1924)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1707)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:71)at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:91)at org.apache.spark.scheduler.DirectTaskResult.value(TaskResult.scala:94)at org.apache.spark.scheduler.TaskResultGetter$$anon$3$$anonfun$run$1.apply$mcV$sp(TaskResultGetter.scala:66)at org.apache.spark.scheduler.TaskResultGetter$$anon$3$$anonfun$run$1.apply(TaskResultGetter.scala:57)at org.apache.spark.scheduler.TaskResultGetter$$anon$3$$anonfun$run$1.apply(TaskResultGetter.scala:57)at org.apache.spark.util.Utils$.logUncaughtExceptions(Utils.scala:1716)at org.apache.spark.scheduler.TaskResultGetter$$anon$3.run(TaskResultGetter.scala:56)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)at java.lang.Thread.run(Thread.java:745)
  • 回答 用户尝试收集大量数据到Driver端,如果Driver端的内存不足以存放这些数据,那么就会抛出OOM(OutOfMemory)的异常,然后Driver端一直在进行GC,尝试回收垃圾来存放返回的数据,导致应用长时间挂起。 解决措施: 如果用户需要在OOM场景下强制将应用退出,那么可以在启动Spark Core应用时,在客户端配置文件“$SPARK_HOME/conf/spark-defaults.conf”中的配置项“spark.driver.extraJavaOptions”中添加如下内容: -XX:OnOutOfMemoryError='kill -9 %p'
  • 回答 问题原因: 在IBM JDK下建立的JDBC connection时间超过登录用户的认证超时时间(默认一天),导致认证失败。 IBM JDK的机制跟Oracle JDK的机制不同,IBM JDK在认证登录后的使用过程中做了时间检查却没有检测外部的时间更新,导致即使显式调用relogin也无法得到刷新。 解决措施: 通常情况下,在发现JDBC connection不可用的时候,可以关闭该connection,重新创建一个connection继续执行。
  • 问题 Structured Streaming的cluster模式,在数据处理过程中终止ApplicationManager,执行应用时显示如下异常。 2017-05-09 20:46:02,393 | INFO | main | client token: Token { kind: YARN_CLIENT_TOKEN, service: } diagnostics: User class threw exception: org.apache.spark.sql.AnalysisException: This query does not support recovering from checkpoint location. Delete hdfs://hacluster/structuredtest/checkpoint/offsets to start over.; ApplicationMaster host: 10.96.101.170 ApplicationMaster RPC port: 0 queue: default start time: 1494333891969 final status: FAILED tracking URL: https://9-96-101-191:8090/proxy/application_1493689105146_0052/ user: spark2x | org.apache.spark.internal.Logging$class.logInfo(Logging.scala:54)Exception in thread "main" org.apache.spark.SparkException: Application application_1493689105146_0052 finished with failed status
  • 回答 原因分析:显示该异常是因为“recoverFromCheckpointLocation”的值判定为false,但却配置了checkpoint目录。 参数“recoverFromCheckpointLocation”的值为代码中“outputMode == OutputMode.Complete()”语句的判断结果(outputMode的默认输出方式为“append”)。 处理方法:编写应用时,用户可以根据具体情况修改数据的输出方式。 将输出方式修改为“complete”,“recoverFromCheckpointLocation”的值会判定为true。此时配置了checkpoint目录时就不会显示异常。
  • 回答 由于checkpoint中包含了spark应用的对象序列化信息、task执行状态信息、配置信息等,因此,当存在以下问题时,从checkpoint恢复spark应用将会失败。 业务代码变更且变更类未明确指定SerialVersionUID。 spark内部类变更,且变更类未明确指定SerialVersionUID。 另外,由于checkpoint保存了部分配置项,因此可能导致业务修改了部分配置项后,从checkpoint恢复时,配置项依然保持为旧值的情况。当前只有以下部分配置会在从checkpoint恢复时重新加载。 "spark.yarn.app.id", "spark.yarn.app.attemptId", "spark.driver.host", "spark.driver.bindAddress", "spark.driver.port", "spark.master", "spark.yarn.jars", "spark.yarn.keytab", "spark.yarn.principal", "spark.yarn.credentials.file", "spark.yarn.credentials.renewalTime", "spark.yarn.credentials.updateTime", "spark.ui.filters", "spark.mesos.driver.frameworkId", "spark.yarn.jars"
  • 回答 Spark任务在运行过程中,driver会创建一个spark-开头的本地临时目录,用于存放业务jar包,配置文件等,同时在本地创建一个blockmgr-开头的本地临时目录,用于存放block data。此两个目录会在Spark应用运行结束时自动删除。 此两个目录的存放路径优先通过SPARK_LOCAL_DIRS环境变量指定,若不存在该环境变量,则设置为spark.local.dir的值,若此配置还不存在,则使用java.io.tmpdir的值。客户端默认配置中spark.local.dir被设置为/tmp,因此默认使用系统/tmp目录。 但存在一些特殊情况,如driver进程未正常退出,比如被kill -9命令结束进程,或者Java虚拟机直接崩溃等场景,导致driver的退出流程未正常执行,则可能导致该部分目录无法被正常清理,残留在系统中。 当前只有yarn-client模式和local模式的driver进程会产生上述问题,在yarn-cluster模式中,已将container内进程的临时目录设置为container临时目录,当container退出时,由container自动清理该目录,因此yarn-cluster模式不存在此问题。
  • 回答 第三方jar包(例如自定义udf)区分x86和TaiShan版本时,混合使用方案: 进入到服务端Spark2x SparkResource的安装目录(集群安装时,SparkResource可能会安装在多个节点上,登录任意一个SparkResource节点,进入到SparkResource的安装目录)。 准备好自己的jar包,例如xx.jar的x86版本和TaiShan版本。将x86版本和TaiShan版本的xx.jar分别复制到当前目录的x86文件夹和TaiShan文件夹里面。 在当前目录下执行以下命令将jar包打包: zip -qDj spark-archive-2x-x86.zip x86/* zip -qDj spark-archive-2x-arm.zip arm/* 执行以下命令查看hdfs上的spark2x依赖的jar包: hdfs dfs -ls /user/spark2x/jars/8.1.0.1 8.1.0.1是版本号,不同版本不同。 执行以下命令移动hdfs上旧的jar包文件到其他目录,例如移动到“tmp”目录。 hdfs dfs -mv /user/spark2x/jars/8.1.0.1/spark-archive-2x-arm.zip /tmp hdfs dfs -mv /user/spark2x/jars/8.1.0.1/spark-archive-2x-x86.zip /tmp 上传3中打包的spark-archive-2x-arm.zip和spark-archive-2x-x86.zip到hdfs的/user/spark2x/jars/8.1.0.1目录下,上传命令如下: hdfs dfs -put spark-archive-2x-arm.zip /user/spark2x/jars/8.1.0.1/ hdfs dfs -put spark-archive-2x-x86.zip /user/spark2x/jars/8.1.0.1/ 上传完毕后删除本地的spark-archive-2x-arm.zip,spark-archive-2x-x86.zip文件。 对其他的sparkResource安装节点执行1~2。 进入webUI重启spark2x的jdbcServer实例。 重启后,需要更新客户端配置。按照客户端所在的机器类型(x86、TaiShan)复制xx.jar的相应版本到客户端的Spark2x安装目录“${install_home}/Spark2x/spark/jars”文件夹中。${install_home}是用户的客户端安装路径,用户需要填写实际的安装目录;若本地的安装目录为“/opt/hadoopclient”,那么就复制相应版本xx.jar到“/opt/hadoopclient/Spark2x/spark/jars”文件夹里。
  • 解决方案 提交yarn-client模式的结构流任务时需要额外如下操作: 将Spark客户端目录下spark-default.conf文件中的spark.driver.extraClassPath配置复制出来,并将Kafka相关jar包路径追加到该配置项之后,提交结构流任务时需要通过--conf将该配置项给加上。例如:kafka相关jar包路径为“/kafkadir”,提交任务需要增加--conf spark.driver.extraClassPath=/opt/client/Spark2x/spark/conf/:/opt/client/Spark2x/spark/jars/*:/opt/client/Spark2x/spark/x86/*:/kafkadir/*。 提交yarn-cluster模式的结构流任务时需要额外如下操作: 将Spark客户端目录下spark-default.conf文件中的spark.yarn.cluster.driver.extraClassPath配置给复制出来,并将Kafka相关jar包相对路径追加到该配置项之后,提交结构流任务时需要通过--conf 将该配置项给加上。例如:kafka相关包为kafka-clients-x.x.x.jar,kafka_2.11-x.x.x.jar,提交任务需要增加--conf spark.yarn.cluster.driver.extraClassPath=/home/huawei/Bigdata/common/runtime/security:./kafka-clients-x.x.x.jar:./kafka_2.11-x.x.x.jar。 当前版本Spark结构流部分不再支持kafka2.x之前的版本,对于升级场景请继续使用旧的客户端。
  • 数据规划 运行样例程序前,需要在Spark客户端的“spark-defaults.conf”配置文件中将配置项“spark.yarn.security.credentials.hbase.enabled”设置为“true”(该参数值默认为“false”,改为“true”后对已有业务没有影响。如果要卸载HBase服务,卸载前请将此参数值改回“false”)。 创建HBase表,构造数据,列需要包含key,modify_time,valid。其中每条数据key值全表唯一,modify_time代表修改时间,valid代表是否为有效数据(该样例中'1'为有效,'0'为无效数据)。 示例:进入hbase shell,执行如下命令: create 'hbase_table','key','info' put 'hbase_table','1','info:modify_time','2019-11-22 23:28:39' put 'hbase_table','1','info:valid','1' put 'hbase_table','2','info:modify_time','2019-11-22 23:28:39' put 'hbase_table','2','info:valid','1' put 'hbase_table','3','info:modify_time','2019-11-22 23:28:39' put 'hbase_table','3','info:valid','0' put 'hbase_table','4','info:modify_time','2019-11-22 23:28:39' put 'hbase_table','4','info:valid','1' 上述数据的modify_time列可设置为当前时间之前的值。 put 'hbase_table','5','info:modify_time','2021-03-03 15:20:39' put 'hbase_table','5','info:valid','1' put 'hbase_table','6','info:modify_time','2021-03-03 15:20:39' put 'hbase_table','6','info:valid','1' put 'hbase_table','7','info:modify_time','2021-03-03 15:20:39' put 'hbase_table','7','info:valid','0' put 'hbase_table','8','info:modify_time','2021-03-03 15:20:39' put 'hbase_table','8','info:valid','1' put 'hbase_table','4','info:valid','0' put 'hbase_table','4','info:modify_time','2021-03-03 15:20:39' 上述数据的modify_time列可设置为样例程序启动后30分钟内的时间值(此处的30分钟为样例程序默认的同步间隔时间,可修改)。 put 'hbase_table','9','info:modify_time','2021-03-03 15:32:39' put 'hbase_table','9','info:valid','1' put 'hbase_table','10','info:modify_time','2021-03-03 15:32:39' put 'hbase_table','10','info:valid','1' put 'hbase_table','11','info:modify_time','2021-03-03 15:32:39' put 'hbase_table','11','info:valid','0' put 'hbase_table','12','info:modify_time','2021-03-03 15:32:39' put 'hbase_table','12','info:valid','1' 上述数据的modify_time列可设置为样例程序启动后30分钟到60分钟内的时间值,即第二次同步周期。 在sparksql中创建HBase的hive外表,命令如下: create table external_hbase_table(key string ,modify_time STRING, valid STRING) using org.apache.spark.sql.hbase.HBaseSource options(hbaseTableName "hbase_table", keyCols "key", colsMapping "modify_time=info.modify_time,valid=info.valid"); 在sparksql中创建CarbonData表: create table carbon01(key string,modify_time STRING, valid STRING) stored as carbondata; 初始化加载当前hbase表中所有数据到CarbonData表; insert into table carbon01 select * from external_hbase_table where valid='1'; 用spark-submit提交命令: spark-submit --master yarn --deploy-mode client --class com.huawei.bigdata.spark.examples.HBaseExternalHivetoCarbon /opt/example/HBaseExternalHivetoCarbon-1.0.jar
  • 运行任务 登录Spark客户端节点,执行如下命令: source 客户端安装目录/bigdata_env source 客户端安装目录/Hudi/component_env 编译构建样例代码后可以使用spark-submit提交命令,执行命令后会依次执行写入、更新、查询、删除等操作: 运行Java样例程序: spark-submit --class com.huawei.bigdata.hudi.examples.HoodieWriteClientExample /opt/example/hudi-java-examples-1.0.jar hdfs://hacluster/tmp/example/hoodie_java hoodie_java 其中:“/opt/example/hudi-java-examples-1.0.jar”为jar包路径,“hdfs://hacluster/tmp/example/hoodie_java”为Hudi表的存储路径,“ hoodie_java”为Hudi表的表名。 运行Scala样例程序: spark-submit --class com.huawei.bigdata.hudi.examples.HoodieDataSourceExample /opt/example/hudi-scala-examples-1.0.jar hdfs://hacluster/tmp/example/hoodie_scala hoodie_scala 其中:“/opt/example/hudi-scala-examples-1.0.jar”为jar包路径,“hdfs://hacluster/tmp/example/hoodie_scala”为Hudi表的存储路径,“ hoodie_Scala”为Hudi表的表名。 运行Python样例程序: spark-submit /opt/example/HudiPythonExample.py hdfs://hacluster/tmp/huditest/example/python hudi_trips_cow 其中:“hdfs://hacluster/tmp/huditest/example/python”为Hudi表的存储路径,“ hudi_trips_cow”为Hudi表的表名。
  • Client HDFS Client主要包括五种方式:JAVA API、C API、Shell、HTTP REST API、WEB UI五种方式,可参考常用API介绍、Shell命令介绍。 JAVA API 提供HDFS文件系统的应用接口,本开发指南主要介绍如何使用Java API进行HDFS文件系统的应用开发。 C API 提供HDFS文件系统的应用接口,使用C语言开发的用户可参考C接口的描述进行应用开发。 Shell 提供shell命令完成HDFS文件系统的基本操作。 HTTP REST API 提供除Shell、Java API和C API以外的其他接口,可通过此接口监控HDFS状态等信息。 WEB UI 提供Web可视化组件管理界面。
  • NameNode 用于管理文件系统的命名空间、目录结构、元数据信息以及提供备份机制等,分为: Active NameNode:主NameNode,管理文件系统的命名空间、维护文件系统的目录结构树以及元数据信息;记录写入的每个“数据块”与其归属文件的对应关系。 Standby NameNode:备NameNode,与主NameNode中的数据保持同步;随时准备在主NameNode出现异常时接管其服务。
  • Hive简介 Hive是一个开源的,建立在Hadoop上的数据仓库框架,提供类似SQL的HQL语言操作结构化数据,其基本原理是将HQL语言自动转换成MapReduce任务或Spark任务,从而完成对Hadoop集群中存储的海量数据进行查询和分析。 Hive主要特点如下: 通过HQL语言非常容易的完成数据提取、转换和加载(ETL)。 通过HQL完成海量结构化数据分析。 灵活的数据存储格式,支持JSON、CSV、TEXTFILE、RCFILE、ORCFILE、SEQUENCEFILE等存储格式,并支持自定义扩展。 多种客户端连接方式,支持JDBC接口。 Hive的主要应用于海量数据的离线分析(如日志分析,集群状态分析)、大规模的数据挖掘(用户行为分析,兴趣分区,区域展示)等场景下。 为保证Hive服务的高可用性、用户数据的安全及访问服务的可控制,在开源社区的Hive-3.1.0版本基础上,Hive新增如下特性: 数据文件加密机制。 开源社区的Hive特性,请参见https://cwiki.apache.org/confluence/display/hive/designdocs。
  • HDFS样例工程介绍 MRS样例工程获取地址为https://github.com/huaweicloud/huaweicloud-mrs-example,切换分支为与MRS集群相匹配的版本分支,然后下载压缩包到本地后解压,即可获取各组件对应的样例代码工程。 当前MRS提供以下HDFS相关样例工程: 表1 HDFS相关样例工程 样例工程位置 描述 hdfs-example-normal HDFS文件操作的Java示例程序。 本工程主要给出了创建HDFS文件夹、写文件、追加文件内容、读文件和删除文件/文件夹等相关接口操作示例。相关业务场景介绍请参见样例代码说明。 hdfs-c-example HDFS C语言开发代码样例。 本示例提供了基于C语言的HDFS文件系统连接、文件操作如创建文件、读写文件、追加文件、删除文件等。相关业务场景介绍请参见C API。 父主题: 概述
  • 开发流程 开发流程中各阶段的说明如图1和表1所示。 图1 Hive应用程序开发流程 表1 Hive应用开发的流程说明 阶段 说明 参考文档 准备开发环境 在进行应用开发前,需首先准备开发环境,推荐使用Java语言进行开发,使用IntelliJ IDEA工具,同时完成JDK、Maven等初始配置。 准备开发环境 准备连接集群配置文件 应用程序开发或运行过程中,需通过集群相关配置文件信息连接MRS集群,配置文件通常包括集群组件信息文件,可从已创建好的MRS集群中获取相关内容。 用于程序调测或运行的节点,需要与MRS集群内节点网络互通,同时配置hosts域名信息。 准备连接集群配置文件 配置并导入样例工程 Hive提供了不同场景下的多种样例程序,用户可获取样例工程并导入本地开发环境中进行程序学习。 配置并导入样例工程 根据业务场景开发程序 根据实际业务场景开发程序,调用组件接口实现对应功能。 开发程序 编译并运行程序 开发好的程序编译运行,用户可在本地Windows开发环境中进行程序调测运行,也可以将程序编译为Jar包后,提交到Linux节点上运行。 调测程序 父主题: 概述
  • 基于API的Glob路径模式以获取LocatedFileStatus和从FileStatus打开文件 在DistributedFileSystem中添加了以下API,以获取具有块位置的FileStatus,并从FileStatus对象打开文件。这些API将减少从客户端到Namenode的RPC调用的数量。 表6 FileSystem API接口说明 Interface接口 Description说明 public LocatedFileStatus[] globLocatedStatus(Path, PathFilter, boolean) throws IOException 返回一个LocatedFileStatus对象数组,其对应文件路径符合路径过滤规则。 public FSDataInputStream open(FileStatus stat) throws IOException 如果stat对象是LocatedFileStatusHdfs的实例,该实例已具有位置信息,则直接创建InputStream而不联系Namenode。
  • 操作步骤 查看运行结果获取应用运行情况 HdfsExample Linux样例程序运行结果如下所示。 [root@192-168-32-144 client]#hadoop jar HDFSTest-XXX.jar com.huawei.bigdata.hdfs.examples.HdfsExampleWARNING: Use "yarn jar" to launch YARN applications.17/10/26 19:11:44 INFO examples.HdfsExample: success to create path /user/hdfs-examples17/10/26 19:11:44 INFO examples.HdfsExample: success to write.17/10/26 19:11:45 INFO examples.HdfsExample: success to append.17/10/26 19:11:45 INFO examples.HdfsExample: result is : hi, I am bigdata. It is successful if you can see me.I append this content.17/10/26 19:11:45 INFO examples.HdfsExample: success to read.17/10/26 19:11:45 INFO examples.HdfsExample: success to delete the file /user/hdfs-examples/test.txt17/10/26 19:11:45 INFO examples.HdfsExample: success to delete path /user/hdfs-examples17/10/26 19:11:45 INFO examples.HdfsExample: success to create path /user/hdfs-examples/hdfs_example_117/10/26 19:11:45 INFO examples.HdfsExample: success to create path /user/hdfs-examples/hdfs_example_017/10/26 19:11:45 INFO examples.HdfsExample: success to write.17/10/26 19:11:45 INFO examples.HdfsExample: success to write.17/10/26 19:11:46 INFO examples.HdfsExample: success to append.17/10/26 19:11:46 INFO examples.HdfsExample: result is : hi, I am bigdata. It is successful if you can see me.I append this content.17/10/26 19:11:46 INFO examples.HdfsExample: success to read.17/10/26 19:11:46 INFO examples.HdfsExample: success to delete the file /user/hdfs-examples/hdfs_example_1/test.txt17/10/26 19:11:46 INFO examples.HdfsExample: success to delete path /user/hdfs-examples/hdfs_example_117/10/26 19:11:46 INFO examples.HdfsExample: success to append.17/10/26 19:11:46 INFO examples.HdfsExample: result is : hi, I am bigdata. It is successful if you can see me.I append this content.17/10/26 19:11:46 INFO examples.HdfsExample: success to read.17/10/26 19:11:46 INFO examples.HdfsExample: success to delete the file /user/hdfs-examples/hdfs_example_0/test.txt17/10/26 19:11:46 INFO examples.HdfsExample: success to delete path /user/hdfs-examples/hdfs_example_0 ColocationExample Linux样例程序运行结果如下所示。 [root@192-168-32-144 client]#hadoop jar HDFSTest-XXX.jar com.huawei.bigdata.hdfs.examples.ColocationExampleWARNING: Use "yarn jar" to launch YARN applications.17/10/26 19:12:38 INFO zookeeper.ZooKeeper: Client environment:zookeeper.version=xxx, built on 10/19/2017 04:21 GMT17/10/26 19:12:38 INFO zookeeper.ZooKeeper: Client environment:host.name=192-168-32-14417/10/26 19:12:38 INFO zookeeper.ZooKeeper: Client environment:java.version=1.8.0_14417/10/26 19:12:38 INFO zookeeper.ZooKeeper: Client environment:java.vendor=Oracle Corporation17/10/26 19:12:38 INFO zookeeper.ZooKeeper: Client environment:java.home=/opt/client/JDK/jdk1.8.0_144/jre......Create Group has finished.Put file is running...Put file has finished.Delete file is running...Delete file has finished.Delete Group is running...Delete Group has finished.17/10/26 19:12:39 INFO zookeeper.ZooKeeper: Session: 0x13000074b7e4687f closed17/10/26 19:12:39 INFO zookeeper.ClientCnxn: EventThread shut down for session: 0x13000074b7e4687f17/10/26 19:12:39 INFO zookeeper.ZooKeeper: Session: 0x12000059699f69e1 closed17/10/26 19:12:39 INFO zookeeper.ClientCnxn: EventThread shut down for session: 0x12000059699f69e1 查看HDFS日志获取应用运行情况 可以查看HDFS的namenode日志了解应用运行情况,并根据日志信息调整应用程序。
  • 功能简介 同分布(Colocation)功能是将存在关联关系的数据或可能要进行关联操作的数据存储在相同的存储节点上。HDFS文件同分布的特性,将那些需进行关联操作的文件存放在相同数据节点上,在进行关联操作计算时避免了到别的数据节点上获取数据,大大降低网络带宽的占用。 在使用Colocation功能之前,建议用户对Colocation的内部机制有一定了解,包括: • Colocation分配节点原理 • 扩容与Colocation分配 • Colocation与数据节点容量 Colocation分配节点原理 Colocation为locator分配数据节点的时候,locator的分配算法会根据已分配的情况,进行均衡的分配数据节点。 locator分配算法的原理是,查询目前存在的所有locators,读取所有locators所分配的数据节点,并记录其使用次数。根据使用次数,对数据节点进行排序,使用次数少的排在前面,优先选择排在前面的节点。每次选择一个节点后,计数加1,并重新排序,选择后续的节点。 扩容与Colocation分配 集群扩容之后,为了平衡地使用所有的数据节点,使新的数据节点的分配频率与旧的数据节点趋于一致,有如下两种策略可以选择,如表1所示。 表1 分配策略 编号 策略 说明 1 删除旧的locators,为集群中所有数据节点重新创建locators。 在未扩容之前分配的locators,平衡的使用了所有数据节点。当扩容后,新加入的数据节点并未分配到已经创建的locators中,所以使用Colocation来存储数据的时候,只会往旧的数据节点存储数据。 由于locators与特定数据节点相关,所以当集群进行扩容的时候,就需要对Colocation的locators分配进行重新规划。 2 创建一批新的locators,并重新规划数据存放方式。 旧的locators使用的是旧的数据节点,而新创建的locators偏重使用新的数据节点,所以需要根据实际业务对数据的使用需求,重新规划locators的使用。 一般的,建议用户在进行集群扩容之后采用策略一来重新分配locators,可以避免数据偏重使用新的数据节点。 Colocation与数据节点容量 由于使用Colocation进行存储数据的时候,会固定存储在指定的locator所对应的数据节点上面,所以如果不对locator进行规划,会造成数据节点容量不均衡。下面总结了保证数据节点容量均衡的两个主要的使用原则,如表2所示。 表2 使用原则 编号 使用原则 说明 1 所有的数据节点在locators中出现的频率一样。 如何保证频率一样:假如数据节点有N个,则创建locators的数量应为N的整数倍(N个、2N个……)。 2 对于所有locators的使用需要进行合理的数据存放规划,让数据均匀的分布在这些locators中。 无 HDFS的二次开发过程中,可以获取DFSColocationAdmin和DFSColocationClient实例,进行从location创建group、删除group、写文件和删除文件的操作。 使用Colocation功能,用户指定了DataNode,会造成某些节点上数据量很大。数据倾斜严重,导致HDFS写任务失败。 由于数据倾斜,导致MapReduce只会在某几个节点访问,造成这些节点上负载很大,而其他节点闲置。 针对单个应用程序任务,只能使用一次DFSColocationAdmin和DFSColocationClient实例。如果每次对文件系统操作都获取此实例,会创建过多HDFS链接,消耗HDFS资源。 Colocation提供了文件同分布的功能,执行集群balancer或mover操作时,会移动数据块,使Colocation功能失效。因此,使用Colocation功能时,建议将HDFS配置项dfs.datanode.block-pinning.enabled设置为true,此时执行集群Balancer或Mover操作时,使用Colocation写入的文件将不会被移动,从而保证了文件同分布。
  • 代码样例 完整样例代码可参考com.huawei.bigdata.hdfs.examples.ColocationExample。 在运行Colocation工程时,需要设置运行用户,此用户需绑定supergroup用户组。 在运行Colocation工程时,HDFS的配置项fs.defaultFS不能配置为viewfs://ClusterX。 初始化 使用Colocation前需要设置运行用户。 private static void init() throws IOException { // 设置用户,若用户没有设置HADOOP_USER_NAME,则使用USER if (System.getenv("HADOOP_USER_NAME") == null && System.getProperty("HADOOP_USER_NAME") == null) { System.setProperty("HADOOP_USER_NAME", USER); }} 获取实例 样例:Colocation的操作使用DFSColocationAdmin和DFSColocationClient实例,在进行创建group等操作前需获取实例。 dfsAdmin = new DFSColocationAdmin(conf); dfs = new DFSColocationClient(); dfs.initialize(URI.create(conf.get("fs.defaultFS")), conf); 创建group 样例:创建一个gid01组,组中包含3个locator。 /** * 创建group * * @throws java.io.IOException */private static void createGroup() throws IOException { dfsAdmin.createColocationGroup(COLOCATION_GROUP_GROUP01, Arrays.asList(new String[] { "lid01", "lid02", "lid03" }));} 写文件,写文件前必须创建对应的group 样例:写入testfile.txt文件。 /** * 创建并写入文件 * * @throws java.io.IOException */private static void put() throws IOException { FSDataOutputStream out = dfs.create(new Path(TESTFILE_TXT), true, COLOCATION_GROUP_GROUP01, "lid01"); // 代写入HDFS的数据 byte[] readBuf = "Hello World".getBytes("UTF-8"); out.write(readBuf, 0, readBuf.length); out.close();} 删除文件 样例:删除testfile.txt文件。 /** * 删除文件 * * @throws java.io.IOException */@SuppressWarnings("deprecation")private static void delete() throws IOException { dfs.delete(new Path(TESTFILE_TXT));} 删除group 样例:删除gid01。 /** * 删除group * * @throws java.io.IOException */private static void deleteGroup() throws IOException { dfsAdmin.deleteColocationGroup(COLOCATION_GROUP_GROUP01);}
  • 代码样例 如下是读文件的代码片段,详细代码请参考com.huawei.bigdata.hdfs.examples中的HdfsExample类。 /** * 读文件 * * @throws java.io.IOException */private void read() throws IOException { String strPath = DEST_PATH + File.separator + FILE_NAME; Path path = new Path(strPath); FSDataInputStream in = null; BufferedReader reader = null; StringBuffer strBuffer = new StringBuffer(); try { in = fSystem.open(path); reader = new BufferedReader(new InputStreamReader(in)); String sTempOneLine; // write file while ((sTempOneLine = reader.readLine()) != null) { strBuffer.append(sTempOneLine); } LOG.info("result is : " + strBuffer.toString()); LOG.info("success to read."); } finally { // make sure the streams are closed finally. IOUtils.closeStream(reader); IOUtils.closeStream(in); }}
  • 代码样例 如下是删除文件的代码片段,详细代码请参考com.huawei.bigdata.hdfs.examples中的HdfsExample类。 /** * 删除目录 * * @throws java.io.IOException */private void rmdir() throws IOException { Path destPath = new Path(DEST_PATH); if (!deletePath(destPath)) { LOG.error("failed to delete destPath " + DEST_PATH); return; } LOG.info("success to delete path " + DEST_PATH);}/** * * @param filePath * @return * @throws java.io.IOException */private boolean deletePath(final Path filePath) throws IOException { if (!fSystem.exists(filePath)) { return false; } // fSystem.delete(filePath, true); return fSystem.delete(filePath, true);}
  • 操作步骤 查看运行结果获取应用运行情况 HdfsExample Windows样例程序运行结果如下所示。 1654 [main] WARN org.apache.hadoop.hdfs.shortcircuit.DomainSocketFactory - The short-circuit local reads feature cannot be used because UNIX Domain sockets are not available on Windows.2013 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to create path /user/hdfs-examples2137 [main] WARN org.apache.hadoop.util.NativeCodeLoader - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable2590 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to write.3245 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to append.4447 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - result is : hi, I am bigdata. It is successful if you can see me.I append this content.4447 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to read.4509 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to delete the file /user/hdfs-examples\test.txt4618 [main] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to delete path /user/hdfs-examples4743 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to create path /user/hdfs-examples/hdfs_example_14743 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to create path /user/hdfs-examples/hdfs_example_05087 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to write.5087 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to write.6507 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to append.6553 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to append.7505 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - result is : hi, I am bigdata. It is successful if you can see me.I append this content.7505 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to read.7568 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to delete the file /user/hdfs-examples/hdfs_example_1\test.txt7583 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - result is : hi, I am bigdata. It is successful if you can see me.I append this content.7583 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to read.7630 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to delete the file /user/hdfs-examples/hdfs_example_0\test.txt7677 [hdfs_example_1] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to delete path /user/hdfs-examples/hdfs_example_17739 [hdfs_example_0] INFO com.huawei.bigdata.hdfs.examples.HdfsExample - success to delete path /user/hdfs-examples/hdfs_example_0 在Windows环境运行样例代码时会出现下面的异常,但是不影响业务: java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries. ColocationExample Windows样例程序运行结果如下所示。 1623 [main] WARN org.apache.hadoop.hdfs.shortcircuit.DomainSocketFactory - The short-circuit local reads feature cannot be used because UNIX Domain sockets are not available on Windows.1670 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:zookeeper.version=***, built on 10/19/2017 04:21 GMT1670 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:host.name=siay7user1.china.huawei.com1670 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:java.version=***1670 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:java.vendor=Oracle Corporation1670 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:java.home=D:\Program Files\Java\jre1.8.0_131......Create Group has finished.Put file is running...5930 [main] WARN org.apache.hadoop.util.NativeCodeLoader - Unable to load native-hadoop library for your platform... using builtin-java classes where applicablePut file has finished.Delete file is running...Delete file has finished.Delete Group is running...Delete Group has finished.6866 [main] INFO org.apache.zookeeper.ZooKeeper - Session: 0x13000074b7e464b7 closed6866 [main-EventThread] INFO org.apache.zookeeper.ClientCnxn - EventThread shut down for session: 0x13000074b7e464b76928 [main-EventThread] INFO org.apache.zookeeper.ClientCnxn - EventThread shut down for session: 0x14000073f13b657b6928 [main] INFO org.apache.zookeeper.ZooKeeper - Session: 0x14000073f13b657b closed 查看HDFS日志获取应用运行情况 可以查看HDFS的NameNode日志了解应用运行情况,并根据日志信息调整应用程序。
  • 代码样例 如下是删除文件的代码片段,详细代码请参考com.huawei.bigdata.hdfs.examples中的HdfsExample类。 /** * 删除文件 * * @throws java.io.IOException */private void delete() throws IOException { Path beDeletedPath = new Path(DEST_PATH + File.separator + FILE_NAME); if (fSystem.delete(beDeletedPath, true)) { LOG.info("success to delete the file " + DEST_PATH + File.separator + FILE_NAME); } else { LOG.warn("failed to delete the file " + DEST_PATH + File.separator + FILE_NAME); }}
  • 代码样例 如下是代码片段,详细代码请参考com.huawei.bigdata.hdfs.examples中的HdfsExample类。 /** * 追加文件内容 * * @throws java.io.IOException */private void append() throws IOException { final String content = "I append this content."; FSDataOutputStream out = null; try { out = fSystem.append(new Path(DEST_PATH + File.separator + FILE_NAME)); out.write(content.getBytes()); out.hsync(); LOG.info("success to append."); } finally { // make sure the stream is closed finally. IOUtils.closeStream(out); }}
  • 代码样例 如下是写文件的代码片段,详细代码请参考com.huawei.bigdata.hdfs.examples中的HdfsExample类。 /** * 创建目录 * * @throws java.io.IOException */ private void mkdir() throws IOException { Path destPath = new Path(DEST_PATH); if (!createPath(destPath)) { LOG.error("failed to create destPath " + DEST_PATH); return; } LOG.info("success to create path " + DEST_PATH);}/** * create file path * * @param filePath * @return * @throws java.io.IOException */private boolean createPath(final Path filePath) throws IOException { if (!fSystem.exists(filePath)) { fSystem.mkdirs(filePath); } return true;}
  • 开发思路 根据前述场景说明进行功能分解,以“/user/hdfs-examples/test.txt”文件的读写删除等操作为例,说明HDFS文件的基本操作流程,可分为以下八部分: 创建FileSystem对象:fSystem。 调用fSystem的mkdir接口创建目录。 调用fSystem的create接口创建FSDataOutputStream对象:out,使用out的write方法写入数据。 调用fSystem的append接口创建FSDataOutputStream对象:out,使用out的write方法追加写入数据。 调用fSystem的open接口创建FSDataInputStream对象:in,使用in的read方法读取文件。 调用fSystem中的delete接口删除文件。 调用fSystem中的delete接口删除文件夹。
共100000条