DataProc Avro版本导致Image v1.0.0上出现错误

时间:2016-08-08 13:52:32

标签: apache-spark google-cloud-platform google-cloud-dataproc

我们正在使用dataproc image 1.0spark-redshift运行一些数据业务作业。

我们有两个集群,这里有一些细节:

  • 群集A - >运行PySpark Streaming作业,上次创建2016. Jul 15. 11:27:12 AEST
  • 群集B - >运行PySpark Ba​​tch作业,每次运行作业时都会创建集群,之后将进行拆卸。
  • A& B运行相同的代码库,使用相同的init脚本,相同的节点类型等。

从上周五的某个时间开始(2016-08-05 AEST),我们的代码停止在群集B上工作,但出现以下错误,而群集A正在运行而没有问题。

以下代码可以在群集B上运行精细时在群集B(或任何具有映像v1.0.0的新群集)上重现该问题。

示例PySpark代码:

from pyspark import SparkContext, SQLContext
sc = SparkContext()
sql_context = SQLContext(sc)

rdd = sc.parallelize([{'user_id': 'test'}])
df = rdd.toDF()

sc._jsc.hadoopConfiguration().set("fs.s3n.awsAccessKeyId", "FOO")
sc._jsc.hadoopConfiguration().set("fs.s3n.awsSecretAccessKey", "BAR")

df\
    .write\
    .format("com.databricks.spark.redshift") \
    .option("url", "jdbc:redshift://foo.ap-southeast-2.redshift.amazonaws.com/bar") \
    .option("dbtable", 'foo') \
    .option("tempdir", "s3n://bar") \
    .option("extracopyoptions", "TRUNCATECOLUMNS") \
    .mode("append") \
    .save()

上述代码在群集 B 上的两种情况下都失败,而在A上运行精细时请注意,RedshiftJDBC41-1.1.10.1010.jar是通过群集初始化创建的脚本。

  • 在主节点上以交互模式运行:

    PYSPARK_DRIVER_PYTHON=ipython pyspark \
        --verbose \
        --master "local[*]"\
        --jars /usr/lib/hadoop/lib/RedshiftJDBC41-1.1.10.1010.jar \
        --packages com.databricks:spark-redshift_2.10:1.0.0 
    
  • 通过gcloud dataproc

    提交作业
    gcloud --project foo \
       dataproc jobs submit pyspark \
       --cluster bar \
       --properties ^#^spark.jars.packages=com.databricks:spark-redshift_2.10:1.0.0#spark.jars=/usr/lib/hadoop/lib/RedshiftJDBC41-1.1.10.1010.jar \
       foo.bar.py
    

它产生的错误(Trace):

2016-08-08 06:12:23 WARN  TaskSetManager:70 - Lost task 6.0 in stage 45.0 (TID 121275, foo.bar.internal): 
    java.lang.NoSuchMethodError: org.apache.avro.generic.GenericData.createDatumWriter(Lorg/apache/avro/Schema;)Lorg/apache/avro/io/DatumWriter;
    at org.apache.avro.mapreduce.AvroKeyRecordWriter.<init>(AvroKeyRecordWriter.java:55)
    at org.apache.avro.mapreduce.AvroKeyOutputFormat$RecordWriterFactory.create(AvroKeyOutputFormat.java:79)
    at org.apache.avro.mapreduce.AvroKeyOutputFormat.getRecordWriter(AvroKeyOutputFormat.java:105)
    at com.databricks.spark.avro.AvroOutputWriter.<init>(AvroOutputWriter.scala:82)
    at com.databricks.spark.avro.AvroOutputWriterFactory.newInstance(AvroOutputWriterFactory.scala:31)
    at org.apache.spark.sql.execution.datasources.BaseWriterContainer.newOutputWriter(WriterContainer.scala:129)
    at org.apache.spark.sql.execution.datasources.DefaultWriterContainer.writeRows(WriterContainer.scala:255)
    at org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelation$$anonfun$run$1$$anonfun$apply$mcV$sp$3.apply(InsertIntoHadoopFsRelation.scala:148)
    at org.apache.spark.sql.execution.datasources.InsertIntoHadoopFsRelation$$anonfun$run$1$$anonfun$apply$mcV$sp$3.apply(InsertIntoHadoopFsRelation.scala:148)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
    at org.apache.spark.scheduler.Task.run(Task.scala:89)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:227)
    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)

2016-08-08 06:12:24 ERROR YarnScheduler:74 - Lost executor 63 on kinesis-ma-sw-o7he.c.bupa-ma.internal: Container marked as failed: container_1470632577663_0003_01_000065 on host: kinesis-ma-sw-o7he.c.bupa-ma.internal. Exit status: 50. Diagnostics: Exception from container-launch.
Container id: container_1470632577663_0003_01_000065
Exit code: 50
Stack trace: ExitCodeException exitCode=50:
    at org.apache.hadoop.util.Shell.runCommand(Shell.java:545)
    at org.apache.hadoop.util.Shell.run(Shell.java:456)
    at org.apache.hadoop.util.Shell$ShellCommandExecutor.execute(Shell.java:722)
    at org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor.launchContainer(DefaultContainerExecutor.java:212)
    at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:302)
    at org.apache.hadoop.yarn.server.nodemanager.containermanager.launcher.ContainerLaunch.call(ContainerLaunch.java:82)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    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)

SparkRedshift:1.0.0需要com.databricks.spark-avro:2.0.1,这需要org.apache.avro:1.7.6

检查群集A上的org.apache.avro.generic.GenericData版本时:

root@foo-bar-m:/home/foo# spark-shell \
>     --verbose \
>     --master "local[*]" \
>     --deploy-mode client \
>     --packages com.databricks:spark-redshift_2.10:1.0.0 \
>     --jars "/usr/lib/hadoop/lib/RedshiftJDBC41-1.1.10.1010.jar"

它产生(Trace):

scala> import org.apache.avro.generic._
import org.apache.avro.generic._

scala> val c = GenericData.get()
c: org.apache.avro.generic.GenericData = org.apache.avro.generic.GenericData@496a514f

scala> c.getClass.getProtectionDomain().getCodeSource()
res0: java.security.CodeSource = (file:/usr/lib/hadoop/lib/bigquery-connector-0.7.5-hadoop2.jar <no signer certificates>)

在群集B上运行相同的命令时:

scala> import org.apache.avro.generic._
import org.apache.avro.generic._

scala> val c = GenericData.get()
c: org.apache.avro.generic.GenericData = org.apache.avro.generic.GenericData@72bec302

scala> c.getClass.getProtectionDomain().getCodeSource()
res0: java.security.CodeSource = (file:/usr/lib/hadoop/lib/bigquery-connector-0.7.7-hadoop2.jar <no signer certificates>)
群集B上的

Screenshot of Env。(对所有删除行为表示道歉)。 我们尝试了在herehere上描述的方法,但没有取得任何成功。

这非常令人沮丧,因为DataProc更新了图像内容而没有将发布版本与不可变版本完全相反。现在我们的代码已经破产,我们无法回滚到以前的版本。

1 个答案:

答案 0 :(得分:1)

抱歉这个麻烦!它当然不是为了打破图像版本中发生的变化。请注意,subminor版本已推出&#34;引擎盖下#34;用于非破坏性错误修复和Dataproc特定补丁。

您可以在上周之前恢复使用1.0。*版本,只需在命令行部署群集时指定--image-version 1.0.8

gcloud dataproc clusters create --image-version 1.0.8

编辑:为了进一步说明,我们调查了相关的Avro版本并验证了Avro版本号在最近的任何Subapor Dataproc版本中实际上都没有 更改。核心问题是Hadoop本身有一个潜在的错误,Hadoop本身在avro-1.7.4下使用/usr/lib/hadoop/lib/而Spark使用avro-1.7.7。巧合的是,Google的bigquery连接也使用了avro-1.7.7,但事实证明它与已知的Spark/Hadoop problem with 1.7.4 vs 1.7.7正交。最近的图像更新被认为是不间断的,因为版本实际上没有改变,但是类加载顺序以不确定的方式改变,其中Hadoop的坏avro版本过去通过纯粹的运气隐藏在Spark工作中,并且不再被意外隐藏在最新的图片中。

Dataproc的preview图像目前包含对Hadoop层中avro版本的修复,该版本应该在任何未来的Dataproc 1.1版本中出现;您可能需要考虑尝试使用preview版本来查看Spark 2.0是否是无缝过渡。