华为云用户手册

  • 回答 HDFS_DELEGATION_TOKEN到期的异常是由于token没有更新或者超出了最大生命周期。 在token的最大生命周期内确保下面的参数值大于作业的运行时间。 “dfs.namenode.delegation.token.max-lifetime”=“604800000”(默认是一星期) 参考修改集群服务配置参数,进入HDFS“全部配置”页面,在搜索框搜索该参数。 建议在token的最大生命周期内参数值为多倍小时数。
  • 回答 NodeManager有重启恢复机制,详情请参见: https://hadoop.apache.org/docs/r3.1.1/hadoop-yarn/hadoop-yarn-site/NodeManager.html#NodeManager_Restart 可以参考修改集群服务配置参数,进入Yarn“全部配置”页面。需将NodeManager的“yarn.nodemanager.recovery.enabled”配置项为“true”后才生效,默认为“true”,这样在YARN重启的异常场景时会定时删除多余的本地日志,避免问题的出现。
  • 回答 当userB对tableB执行insert操作后,会在外表数据路径下生成新的数据文件,且文件属组是userB,当userA查询tableA时,会读取外表数据目录下的所有的文件,此时会因没有userB生成的文件的读取权限而查询失败。 实际上,不只是查询场景,还有其他场景也会出现问题。例如:inset overwrite操作将会把此目录下的其他表文件也一起复写。 由于Spark SQL当前的实现机制,如果对此种场景添加检查限制,会存在一致性问题和性能问题,因此未对此种场景添加限制,但是用户应避免此种用法,以避免此场景带来的各种问题。
  • 回答 在JobHistory界面中跳转到某个应用的原生页面时,JobHistory需要回放该应用的Event log,若应用包含的事件日志较大,则回放时间较长,浏览器需要较长时间的等待。 当前浏览器访问JobHistory原生页面需经过httpd代理,代理的超时时间是10分钟,因此,如果JobHistory在10分钟内无法完成Event log的解析并返回,httpd会主动向浏览器返回Proxy Error信息。
  • 回答 JobHistory服务更新页面上的app时,会根据HDFS上的part文件大小变更与否判断是否刷新首页面的app显示信息。若文件为第一次查看,则将当前文件大小与0作比较,如果大于0则读取该文件。 分组的情况下,如果执行的app没有job处于执行状态,则part文件为空,即JobHistory服务不会读取该文件,此app也不会显示在JobHistory页面上。但若part文件大小之后有更新,JobHistory又会显示该app。
  • 问题 在Spark2x的spark-shell上执行如下代码失败: val acctId = List(("49562", "Amal", "Derry"), ("00000", "Fred", "Xanadu"))val rddLeft = sc.makeRDD(acctId)val dfLeft = rddLeft.toDF("Id", "Name", "City")//dfLeft.showval acctCustId = List(("Amal", "49562", "CO"), ("Dave", "99999", "ZZ"))val rddRight = sc.makeRDD(acctCustId)val dfRight = rddRight.toDF("Name", "CustId", "State")//dfRight.showval dfJoin = dfLeft.join(dfRight, dfLeft("Id") === dfRight("CustId"), "outer")dfJoin.showdfJoin.repartition(1).write.format("com.databricks.spark.csv").option("delimiter", "\t").option("header", "true").option("treatEmptyValuesAsNulls", "true").option("nullValue", "").save("/tmp/outputDir")
  • 问题 在History Server页面中访问某个Spark应用的页面时,发现访问时出错。 查看相应的HistoryServer日志后,发现有“FileNotFound”异常,相关日志如下所示: 2016-11-22 23:58:03,694 | WARN | [qtp55429210-232] | /history/application_1479662594976_0001/stages/stage/ | org.sparkproject.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:628)java.io.FileNotFoundException: ${BIGDATA_HOME}/tmp/spark/jobHistoryTemp/blockmgr-5f1f6aca-2303-4290-9845-88fa94d78480/09/temp_shuffle_11f82aaf-e226-46dc-b1f0-002751557694 (No such file or directory)
  • 回答 Kafka重启成功后应用会按照batch时间把2017/05/11 10:57:00~2017/05/11 10:58:00缺失的RDD补上(如图2所示),尽管UI界面上显示读取的数据个数为“0”,但实际上这部分数据在补的RDD中进行了处理,因此,不存在数据丢失。 Kafka重启时间段的数据处理机制如下。 Spark Streaming应用使用了state函数(例如:updateStateByKey),在Kafka重启成功后,Spark Streaming应用生成2017/05/11 10:58:00 batch任务时,会按照batch时间把2017/05/11 10:57:00~2017/05/11 10:58:00缺失的RDD补上(Kafka重启前Kafka上未读取完的数据,属于2017/05/11 10:57:00之前的batch),如图2所示。 图2 重启时间段缺失数据处理机制
  • 回答 经过定位发现,导致这个问题的原因是:Spark Streaming的计算核数少于Receiver的个数,导致部分Receiver启动以后,系统已经没有资源去运行计算任务,导致第一个任务一直在等待,后续任务一直在排队。从现象上看,就是如问题中的图1中所示,会有两个任务一直在等待。 因此,当Web出现两个任务一直在等待的情况,首先检查Spark的核数是否大于Receiver的个数。 Receiver在Spark Streaming中是一个常驻的Spark Job,Receiver对于Spark是一个普通的任务,但它的生命周期和Spark Streaming任务相同,并且占用一个核的计算资源。 在调试和测试等经常使用默认配置的场景下,要时刻注意核数与Receiver个数的关系。
  • 回答 问题原因: ApplicationMaster进程中有1个Credential Refresh Thread会根据token renew周期 * 0.75的时间比例上传更新后的Credential文件到HDFS上。 Executor进程中有1个Credential Refresh Thread会根据token renew周期 *0.8的时间比例去HDFS上获取更新后的Credential文件,用来刷新UserGroupInformation中的token,避免token失效。 当Executor进程的Credential Refresh Thread发现当前时间已经超过Credential文件更新时间(即token renew周期 *0.8)时,会等待1分钟再去HDFS上面获取最新的Credential文件,以确保AM端已经将更新后的Credential文件放到HDFS上。 当“dfs.namenode.delegation.token.renew-interval”配置值小于60秒,Executor进程起来时发现当前时间已经超过Credential文件更新时间,等待1分钟再去HDFS上面获取最新的Credential文件,而此时token已经失效,task运行失败,然后在其他Executor上重试,由于重试时间都是在1分钟内完成,所以task在其他Executor上也运行失败,导致运行失败的Executor加入到黑名单,没有可用的Executor,应用退出。 修改方案: 在Spark使用场景下,需设置“dfs.namenode.delegation.token.renew-interval”大于80秒。“dfs.namenode.delegation.token.renew-interval”参数描述请参表1考。 表1 参数说明 参数 描述 默认值 dfs.namenode.delegation.token.renew-interval 该参数为服务器端参数,设置token renew的时间间隔,单位为毫秒。 86400000
  • 问题 在Spark Streaming应用执行过程中重启Kafka时,应用无法从Kafka获取topic offset,从而导致生成Job失败。如图1所示,其中2017/05/11 10:57:00~2017/05/11 10:58:00为Kafka重启时间段。2017/05/11 10:58:00重启成功后对应的“Input Size”的值显示为“0 records”。 图1 Web UI界面部分batch time对应Input Size为0 records
  • 回答 问题根因: 上述两个问题是由于多主实例模式或者多租户模式下,使用spark-beeline通过add jar的方式创建function,此function在各个JDBCServer实例之间是不可见的。执行drop function时,如果该session连接的JDBCServer实例不是创建function的JDBCServer实例,则在该session中找不到该function,而且hive默认将“hive.exec.drop.ignorenonexistent”设置为“true”,即当function不存在时,删除function操作不会报错,这样就表现出了用户没有drop function的权限,执行drop时却没有报错,让用户误以为drop成功;但重新起session时又连到创建function的JDBCServer上,因此执行show function,function仍然存在。该行为是hive的社区行为。 修改方案: 在执行drop function命令之前先执行add jar命令,则该function在有权限的情况下才能drop成功,且drop成功之后不会出现show function仍然存在的现象。
  • 回答 原因分析: 这是由于Spark2x与Spark1.5存储DataSoure表信息的格式不一致导致的。Spark1.5会将schema信息分成多个part,使用path.park.0作为key进行存储,读取时再将各个part都读取出来,重新拼成完整的信息。而Spark2x直接使用相应的key获取对应的信息。这样在Spark2x中去读取Spark1.5创建的DataSource表时,就无法成功读取到key对应的信息,导致解析DataSource表信息失败。 而在处理Hive格式的表时,Spark2x与Spark1.5的存储方式一致,所以Spark2x可以直接读取Spark1.5创建的表,不存在上述问题。 规避措施: Spark2x可以通过创建外表的方式来创建一张指向Spark1.5表实际数据的表,这样可以实现在Spark2x中读取Spark1.5创建的DataSource表。同时,Spark1.5更新过数据后,Spark2x中访问也能感知到变化 ,反过来一样。这样即可实现Spark2x对Spark1.5创建的DataSource表的访问。
  • 解答 该应用程序中使用了DStream中的print算子来显示结果,该算子会调用RDD中的take算子来实现底层的计算。 Take算子会以Partition为单位多次触发计算。 在该问题中,由于Shuffle操作,导致take算子默认有两个Partition,Spark首先计算第一个Partition,但由于没有数据输入,导致获取结果不足10个,从而触发第二次计算,因此会出现RDD的DAG结构打印两次的现象。 在代码中将print算子修改为foreach(collect),该问题则不会出现。
  • 问题 运行一个Spark Streaming任务,确认有数据输入后,发现没有任何处理的结果。打开Web界面查看Spark Job执行情况,发现如下图所示:有两个Job一直在等待运行,但一直无法成功运行。 图1 Active Jobs 继续查看已经完成的Job,发现也只有两个,说明Spark Streaming都没有触发数据计算的任务(Spark Streaming默认有两个尝试运行的Job,就是图中两个) 图2 Completed Jobs
  • 回答 在开启钨丝计划(即tungsten功能)后,Spark对于部分执行计划会使用codegen的方式来生成Java代码,但JDK编译时要求Java代码中的每个函数的长度不能超过64KB。当执行一个很复杂的SQL语句时,例如有多层语句嵌套,且单层语句中对字段有大量的逻辑处理(如多层嵌套的case when语句),这种情况下,通过codegen生成的Java代码中函数的大小就可能会超过64KB,从而导致编译失败。 规避措施: 当出现上述问题时,用户可以通过关闭钨丝计划,关闭使用codegen的方式来生成Java代码的功能,从而确保语句的正常执行。即在客户端的“spark-defaults.conf”配置文件中将“spark.sql.codegen.wholeStage”配置为“false”。
  • 回答 场景一: add jar语句只会将jar加载到当前连接的JDBCServer的jarClassLoader,不同JDBCServer不会共用。JDBCServer重启后会创建新的jarClassLoader,所以需要重新add jar。 添加jar包有两种方式:可以在启动spark-sql的时候添加jar包,如spark-sql --jars /opt/test/two_udfs.jar;也可在spark-sql启动后再添加jar包,如add jar /opt/test/two_udfs.jar。add jar所指定的路径可以是本地路径也可以是HDFS上的路径。
  • 问题 问题一: 用户没有drop function的权限,能够drop成功。具体场景如下: 在FusionInsight Manager页面上添加user1用户,给予用户admin权限,执行下列操作: set role admin;add jar /home/smartcare-udf-0.0.1-SNAPSHOT.jar;create database db4;use db4;create function f11 as 'com.huawei.smartcare.dac.hive.udf.UDFArrayGreaterEqual';create function f12 as 'com.huawei.smartcare.dac.hive.udf.UDFArrayGreaterEqual'; 修改user1用户,取消admin权限,执行下列操作: drop functiondb4.f11; 结果显示drop成功,如图1所示。 图1 用户没有权限却drop成功结果 问题二: 用户drop function成功,show function的时候,function仍然存在。具体场景如下: 在FusionInsight Manager页面上添加user1用户,给予用户admin权限,进入spark-beeline执行下列操作: set role admin;create database db2;use db2;add jar /home/smartcare-udf-0.0.1-SNAPSHOT.jar;create function f11 as 'com.huawei.smartcare.dac.hive.udf.UDFArrayGreaterEqual';create function f12 as 'com.huawei.smartcare.dac.hive.udf.UDFArrayGreaterEqual'; 退出后再进入spark-beeline执行下列操作: set role admin;use db2;drop function db2.f11; 退出后再进入spark-beeline执行下列操作: use db2;show functions; 结果显示,被drop的function仍然存在,如图2所示。 图2 执行show functions操作后的结果
  • 回答 当前在默认配置下,在内存中保留的Job和Stage的UI数据个数为1000个。 当前大集群优化已增加将UI数据溢出到磁盘的优化,其溢出条件是每个Stage中的UI数据大小达到最小阈值5MB。如果每个Stage的task数较小,那么其UI数据大小可能达不到该阈值,从而导致该Stage的UI数据一直缓存在内存中,直到UI数据个数到达保留的上限值(当前默认值为1000个),旧的UI数据才会在内存中被清除。 因此,在将旧的UI数据从内存中清除之前,UI数据会占用大量内存,从而导致执行10T的TPCDS测试套时出现Driver内存不足的现象。 规避措施: 根据业务需要,配置合适的需要保留的Job和Stage的UI数据个数,即配置“spark.ui.retainedJobs”和“spark.ui.retainedStages”参数。详细信息请参考常用参数中的表13。 如果需要保留的Job和Stage的UI数据个数较多,可通过配置“spark.driver.memory”参数,适当增大Driver的内存。详细信息请参考常用参数中的表10。
  • 问题 当执行一个很复杂的SQL语句时,例如有多层语句嵌套,且单层语句中对字段有大量的逻辑处理(如多层嵌套的case when语句),此时执行该语句会报如下所示的错误日志,该错误表明某个方法的代码超出了64KB。 java.util.concurrent.ExecutionException: java.lang.Exception: failed to compile: org.codehaus.janino.JaninoRuntimeException: Code of method "(Lorg/apache/spark/sql/catalyst/expressions/GeneratedClass$SpecificUnsafeProjection;Lorg/apache/spark/sql/catalyst/InternalRow;)V" of class "org.apache.spark.sql.catalyst.expressions.GeneratedClass$SpecificUnsafeProjection" grows beyond 64 KB
  • 回答 当前JDBCServer中存在两个线程池HiveServer2-Handler-Pool和HiveServer2-Background-Pool,其中HiveServer2-Handler-Pool用于处理session连接,HiveServer2-Background-Pool用于处理SQL语句的执行。 当前的健康检查机制是通过新增一个session连接,并在该session所在的线程中执行健康检查命令HEALTHCHECK来判断SparkJDBCServer的健康状况,因此HiveServer2-Handler-Pool必须保留一个线程,用于处理健康检查的session连接和健康检查命令执行,否则将导致无法建立健康检查的session连接或健康检查命令无法执行,从而认为Spark JDBCServer不健康而被Kill。即如果当前HiveServer2-Handler-Pool的线程池数为100,那么最多支持连接99个session。
  • 问题 为什么日期类型的字段作为过滤条件时匹配'2016-6-30'时没有查询结果,匹配'2016-06-30'时有查询结果。 如下图所示:“select count(*)from trxfintrx2012 a where trx_dte_par='2016-6-30'”,其中trx_dte_par为日期类型的字段,当过滤条件为“where trx_dte_par='2016-6-30'”时没有查询结果,当过滤条件为“where trx_dte_par='2016-06-30'”时有查询结果。
  • 问题 使用默认配置时,16T的文本数据转成4T Parquet数据失败,报如下错误信息。 Job aborted due to stage failure: Task 2866 in stage 11.0 failed 4 times, most recent failure: Lost task 2866.6 in stage 11.0 (TID 54863, linux-161, 2): java.io.IOException: Failed to connect to /10.16.1.11:23124at org.apache.spark.network.client.TransportClientFactory.createClient(TransportClientFactory.java:214)at org.apache.spark.network.client.TransportClientFactory.createClient(TransportClientFactory.java:167)at org.apache.spark.network.netty.NettyBlockTransferService$$anon$1.createAndStart(NettyBlockTransferService.scala:92) 使用的默认配置如表1所示。 表1 参数说明 参数 描述 默认值 spark.sql.shuffle.partitions shuffle操作时,shuffle数据的分块数。 200 spark.shuffle.sasl.timeout shuffle操作时SASL认证的超时时间。单位:秒。 120s spark.shuffle.io.connectionTimeout shuffle操作时连接远程节点的超时时间。单位:秒。 120s spark.network.timeout 所有涉及网络连接操作的超时时间。单位:秒。 360s
  • 问题 执行大数据量的Spark任务(如2T的TPCDS测试套),任务运行成功后,在spark-sql退出时概率性出现RejectedExecutionException的异常栈信息,相关日志如下所示: 16/07/16 10:19:56 ERROR TransportResponseHandler: Still have 2 requests outstanding when connection from linux-192/10.1.1.5:59250 is closedjava.util.concurrent.RejectedExecutionException: Task scala.concurrent.impl.CallbackRunnable@5fc1ab rejected from java.util.concurrent.ThreadPoolExecutor@52fa7e19[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 3025]
  • 操作步骤 访问Hue WebUI,请参考访问Hue的WebUI。 在左侧导航栏单击编辑器,然后选择“Hive”。 在“Database”右侧下拉列表选择一个Hive中的数据库,默认数据库为“default”。 系统将自动显示数据库中的所有表。可以输入表名关键字,系统会自动搜索包含此关键字的全部表。 单击指定的表名,可以显示表中所有的列。 在HiveQL语句编辑区输入HiveQL语句。 create table hue_table(id int,name string,company string) row format delimited fields terminated by ',' stored as textfile; 单击 开始执行HiveQL语句。 图1 执行语句 在命令输入框内输入show tables;,单击按钮,查看“结果”中有5创建的表hue_table。
  • 回答 JDBCServer方式使用了ShuffleService功能,Reduce阶段所有的Executor会从NodeManager中获取数据,当数据量达到一个级别(10T级别),会出现NodeManager单点瓶颈(ShuffleService服务在NodeManager进程中),就会出现某些Task获取数据超时,从而出现该问题。 因此,当数据量达到10T级别以上的Spark任务,建议用户关闭ShuffleService功能,即在“Spark-defaults.conf”配置文件中将配置项“spark.shuffle.service.enabled”配置为“false”。
  • 回答 Spark SQL对用户SQL语句的执行逻辑是:首先解析出语句中包含的表,再获取表的元数据信息,然后对权限进行检查。 当表是parquet表时,元数据信息包括文件的Split信息。Split信息需要调用HDFS的接口去读取,当表包含的文件数量很多时,串行读取Split信息变得缓慢,影响性能。故对此做了优化,当表包含的文件大于一定阈值(即spark.sql.sources.parallelSplitDiscovery.threshold参数值)时,会生成一个Job,利用Executor的并行能力去读取,从而提升执行效率。 由于权限检查在获取表元数据之后,因此当读取的parquet表包含的文件数量很多时,会在报“Missing Privileges”之前,运行一个Job来并行读取元数据信息。
  • 问题 当创建了表名为table的表后,执行drop table table上报以下错误,或者执行其他操作也会出现类似错误。 16/07/12 18:56:29 ERROR SparkSQLDriver: Failed in [drop table table]java.lang.RuntimeException: [1.1] failure: identifier expectedtable^at scala.sys.package$.error(package.scala:27)at org.apache.spark.sql.catalyst.SqlParserTrait$class.parseTableIdentifier(SqlParser.scala:56)at org.apache.spark.sql.catalyst.SqlParser$.parseTableIdentifier(SqlParser.scala:485)
  • 回答 Spark SQL可以将表cache到内存中,并且使用压缩存储来尽量减少内存压力。通过将表cache,查询可以直接从内存中读取数据,从而减少读取磁盘带来的内存开销。 但需要注意的是,被cache的表会占用executor的内存。尽管在Spark SQL采用压缩存储的方式来尽量减少内存开销、缓解GC压力,但当缓存的表较大或者缓存表数量较多时,将不可避免的影响executor的稳定性。 此时的最佳实践是,当不需要将表cache来实现查询加速时,应及时将表进行uncache以释放内存。可以执行命令uncache table table_name来uncache表。 被cache的表也可以在Spark Driver UI的Storage标签里查看。
  • 回答 由于Spark存在一个机制,为了提高性能会缓存Parquet的元数据信息。当通过Hive或其他方式更新了Parquet表时,缓存的元数据信息未更新,导致Spark SQL查询不到新插入的数据。 对于存储类型为Parquet的Hive分区表,在执行插入数据操作后,如果分区信息未改变,则缓存的元数据信息未更新,导致Spark SQL查询不到新插入的数据。 解决措施:在使用Spark SQL查询之前,需执行Refresh操作更新元数据信息。 REFRESH TABLE table_name; table_name为刷新的表名,该表必须存在,否则会出错。 执行查询语句时,即可获取到最新插入的数据。 Spark官网提供了此机制的描述,详情请参见:https://spark.apache.org/docs/3.1.1/sql-programming-guide.html#metadata-refreshing
共100000条