我使用hbase-spark在我的spark-streaming项目中记录pv / uv。然后,当我杀死应用程序并重新启动它时,我在检查点恢复时遇到异常:
16/03/02 10:17:21错误HBaseContext:无法从广播中获取getConfig java.lang.ClassCastException:[B无法强制转换为org.apache.spark.SerializableWritable 在com.paitao.xmlife.contrib.hbase.HBaseContext.getConf(HBaseContext.scala:645) at com.paitao.xmlife.contrib.hbase.HBaseContext.com $ paitao $ xmlife $ contrib $ hbase $ HBaseContext $$ hbaseForeachPartition(HBaseContext.scala:627) at com.paitao.xmlife.contrib.hbase.HBaseContext $$ anonfun $ com $ paitao $ xmlife $ contrib $ hbase $ HBaseContext $$ bulkMutation $ 1.apply(HBaseContext.scala:457) at com.paitao.xmlife.contrib.hbase.HBaseContext $$ anonfun $ com $ paitao $ xmlife $ contrib $ hbase $ HBaseContext $$ bulkMutation $ 1.apply(HBaseContext.scala:457) 在org.apache.spark.rdd.RDD $$ anonfun $ foreachPartition $ 1 $$ anonfun $ apply $ 29.apply(RDD.scala:898) 在org.apache.spark.rdd.RDD $$ anonfun $ foreachPartition $ 1 $$ anonfun $ apply $ 29.apply(RDD.scala:898) 在org.apache.spark.SparkContext $$ anonfun $ runJob $ 5.apply(SparkContext.scala:1839) 在org.apache.spark.SparkContext $$ anonfun $ runJob $ 5.apply(SparkContext.scala:1839) 在org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66) 在org.apache.spark.scheduler.Task.run(Task.scala:88) 在org.apache.spark.executor.Executor $ TaskRunner.run(Executor.scala:214) 在java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:617) 在java.lang.Thread.run(Thread.java:745)
我检查了HBaseContext的代码,它使用广播来存储HBase配置。
class HBaseContext(@transient sc: SparkContext,
@transient config: Configuration,
val tmpHdfsConfgFile: String = null) extends Serializable with Logging {
@transient var credentials = SparkHadoopUtil.get.getCurrentUserCredentials()
@transient var tmpHdfsConfiguration: Configuration = config
@transient var appliedCredentials = false
@transient val job = Job.getInstance(config)
TableMapReduceUtil.initCredentials(job)
// <-- broadcast for HBaseConfiguration here !!!
var broadcastedConf = sc.broadcast(new SerializableWritable(config))
var credentialsConf = sc.broadcast(new SerializableWritable(job.getCredentials()))
...
当checkpoint-recover时,它试图在其getConf函数中访问此广播值:
if (tmpHdfsConfiguration == null) {
try {
tmpHdfsConfiguration = configBroadcast.value.value
} catch {
case ex: Exception => logError("Unable to getConfig from broadcast", ex)
}
}
然后引发异常。我的问题是:是否有可能在spark应用程序中从检查点恢复广播值?我们还有一些其他解决方案可以在恢复后重新广播值吗?
感谢您的反馈!
答案 0 :(得分:1)
目前,它是Spark的一个已知错误。贡献者一直在调查这个问题,但没有取得任何进展。
这是我的解决方法:我不是将数据加载到广播变量并向所有执行者广播,而是让每个执行者将数据本身加载到单个对象中。
顺便说一句,请按照此问题进行更改https://issues.apache.org/jira/browse/SPARK-5206
答案 1 :(得分:1)
遵循以下方法
当流作业在检查点目录中没有数据开始时,它将初始化广播变量。
重新启动流式传输时,它将从检查点目录中恢复广播变量。