Apache spark DataProc Avro版本导致映像v1.0.0出现错误
我们正在使用和运行一些dataproc作业 我们有两个集群,以下是一些详细信息:Apache spark DataProc Avro版本导致映像v1.0.0出现错误,apache-spark,google-cloud-platform,google-cloud-dataproc,Apache Spark,Google Cloud Platform,Google Cloud Dataproc,我们正在使用和运行一些dataproc作业 我们有两个集群,以下是一些详细信息: 集群A->运行PySpark流媒体作业,上次创建2016。七月十五号。11:27:12 AEST Cluster B->运行PySpark批处理作业,每次运行作业时都会创建集群,然后拆卸 A&B运行相同的代码库,使用相同的初始化脚本,相同的节点类型等 自上周五某个时候以来(2016-08-05 AEST),我们的代码在集群B上停止工作,出现以下错误,而集群A运行时没有问题 以下代码可以在群集A上运行fine时
- 集群A->运行PySpark流媒体作业,上次创建
2016。七月十五号。11:27:12 AEST
- Cluster B->运行PySpark批处理作业,每次运行作业时都会创建集群,然后拆卸李>
- A&B运行相同的代码库,使用相同的初始化脚本,相同的节点类型等
自上周五某个时候以来(
2016-08-05 AEST
),我们的代码在集群B上停止工作,出现以下错误,而集群A运行时没有问题
以下代码可以在群集A上运行fine时,在群集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上运行fine。请注意,是通过群集初始化脚本创建的
- 在主节点上以交互模式运行:
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
它产生的错误(): 它产生():
scala>import org.apache.avro.generic_
导入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=(文件:/usr/lib/hadoop/lib/bigquery-connector-0.7.5-hadoop2.jar)
在群集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>)
scala>import org.apache.avro.generic_
导入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=(文件:/usr/lib/hadoop/lib/bigquery-connector-0.7.7-hadoop2.jar)
在集群B上(对所有修订表示歉意)。 我们尝试了上面描述的方法,但没有成功
这确实令人沮丧,因为DataProc更新图像内容,而没有将发布版本与不可变版本完全对立起来。现在我们的代码被破坏了,我们无法回滚到以前的版本 很抱歉给您添麻烦!它当然不是为了破坏图像版本中发生的更改。请注意,subminor版本是“在引擎盖下”推出的,用于非破坏性错误修复和Dataproc特定补丁 从命令行部署集群时,只需指定
--image version 1.0.8
,即可恢复使用上周之前的1.0.*版本:
gcloud dataproc clusters create --image-version 1.0.8
编辑:为了进一步澄清,我们已经调查了有问题的Avro版本,并验证了Avro版本号在最近的subminor Dataproc版本中实际上没有改变。核心问题是Hadoop本身有一个潜在的bug,Hadoop本身在/usr/lib/Hadoop/lib/
下引入了avro-1.7.4
,Spark使用了avro-1.7.7
。巧合的是,谷歌的BigQueryConnectory也使用了avro-1.7.7,但事实证明这与已知的数据是正交的。最近的映像更新被认为是非破坏性的,因为版本事实上没有改变,但是类加载顺序以一种不确定的方式改变了,Hadoop的坏avro版本过去被完全幸运地从Spark作业中隐藏,并且不再意外地隐藏在最新的映像中
Dataproc的
预览
图像目前包括对Hadoop层中的avro版本的修复,该版本将在未来的Dataproc 1.1版本中发布;您可能需要考虑尝试<代码>预览< /Cord>版本,看看ScIP 2是否是无缝转换。谢谢您的详细解释,现在更清楚了。1.0.8版和预览版都经过测试运行良好。这个问题可能有点脱离上下文,关于类路径加载顺序问题,我们已经尝试了spark.driver.userClassPathFirst
和spark.executor.userClassPathFirst
,但它们都不起作用。不知道你对此有什么见解?谢谢。不幸的是,我没有太多机会玩spark.driver.userClassPathFirst;如果我不得不猜测,我会怀疑它主要适用于提交uber JAR,直接捆绑精确的依赖项,如果--packages
中引用的依赖项不能从特殊的类加载器设置中获益,我也不会感到惊讶。
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>)
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>)
gcloud dataproc clusters create --image-version 1.0.8