Scala try-catch块未捕获异常

Scala try-catch块未捕获异常,scala,apache-spark,exception-handling,try-catch,spark-streaming,Scala,Apache Spark,Exception Handling,Try Catch,Spark Streaming,我正在将DStream保存到Cassandra。Cassandra中有一列数据类型为mapdatatype。Cassandra不支持Map中的null值,但流中可能出现null值 我已经添加了trycatch如果出现问题,但是程序停止了,我在日志中没有看到错误消息: 试试看{ saveToCassandra(“表”、“键空间”) }抓住{ 案例e:Exception=>log.error(“在Cassandra中保存数据时出错”+e.getMessage,e) } 例外情况 原因:java.l

我正在将
DStream
保存到Cassandra。Cassandra中有一列数据类型为
map
datatype。Cassandra不支持Map中的
null
值,但流中可能出现null值

我已经添加了
try
catch
如果出现问题,但是程序停止了,我在日志中没有看到错误消息:

试试看{
saveToCassandra(“表”、“键空间”)
}抓住{
案例e:Exception=>log.error(“在Cassandra中保存数据时出错”+e.getMessage,e)
}
例外情况

原因:java.lang.NullPointerException:映射值不能为null
位于com.datasax.driver.core.TypeCodec$AbstractMapCodec.serialize(TypeCodec.java:2026)
位于com.datasax.driver.core.TypeCodec$AbstractMapCodec.serialize(TypeCodec.java:1909)
位于com.datastax.driver.core.AbstractData.set(AbstractData.java:530)
位于com.datastax.driver.core.AbstractData.set(AbstractData.java:536)
位于com.datastax.driver.core.BoundStatement.set(BoundStatement.java:870)
在com.datastax.spark.connector.writer.BoundStatementBuilder.com$datastax$spark$connector$writer$BoundStatementBuilder$$bindColumnUnset(BoundStatementBuilder.scala:73)
在com.datastax.spark.connector.writer.BoundStatementBuilder$$anonfun$6.apply(BoundStatementBuilder.scala:84)上
在com.datastax.spark.connector.writer.BoundStatementBuilder$$anonfun$6.apply(BoundStatementBuilder.scala:84)上
在com.datastax.spark.connector.writer.BoundStatementBuilder$$anonfun$bind$1.apply$mcVI$sp(BoundStatementBuilder.scala:106)
位于scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
在com.datastax.spark.connector.writer.BoundStatementBuilder.bind(BoundStatementBuilder.scala:101)上
在com.datastax.spark.connector.writer.GroupingBatchBuilder.next(GroupingBatchBuilder.scala:106)上
在com.datastax.spark.connector.writer.GroupingBatchBuilder.next(GroupingBatchBuilder.scala:31)
位于scala.collection.Iterator$class.foreach(Iterator.scala:893)
位于com.datastax.spark.connector.writer.GroupingBatchBuilder.foreach(GroupingBatchBuilder.scala:31)
在com.datastax.spark.connector.writer.TableWriter$$anonfun$writeInternal$1.apply(TableWriter.scala:233)
在com.datastax.spark.connector.writer.TableWriter$$anonfun$writeInternal$1.apply(TableWriter.scala:210)
在com.datastax.spark.connector.cql.CassandraConnector$$anonfun$和sessiondo$1.apply上(CassandraConnector.scala:112)
在com.datastax.spark.connector.cql.CassandraConnector$$anonfun$和sessiondo$1.apply(CassandraConnector.scala:111)
在com.datasax.spark.connector.cql.CassandraConnector.closeResourceAfterUse(CassandraConnector.scala:145)上
在com.datasax.spark.connector.cql.CassandraConnector.withSessionDo上(CassandraConnector.scala:111)
在com.datastax.spark.connector.writer.TableWriter.writeInternal(TableWriter.scala:210)
在com.datastax.spark.connector.writer.TableWriter.insert(TableWriter.scala:197)
在com.datastax.spark.connector.writer.TableWriter.write上(TableWriter.scala:183)
在com.datastax.spark.connector.streaming.DStreamFunctions$$anonfun$saveToCassandra$1$$anonfun$apply$1.apply(DStreamFunctions.scala:54)
在com.datastax.spark.connector.streaming.DStreamFunctions$$anonfun$saveToCassandra$1$$anonfun$apply$1.apply(DStreamFunctions.scala:54)
位于org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
位于org.apache.spark.scheduler.Task.run(Task.scala:109)
位于org.apache.spark.executor.executor$TaskRunner.run(executor.scala:345)
... 3个以上

我想知道为什么尽管有try/catch块,程序还是停止了。为什么没有捕捉到异常?

问题在于,您没有捕捉到您认为自己捕捉到的异常。您拥有的代码将捕获一个驱动程序异常,事实上,像这样构造的代码就可以做到这一点

然而,这并不意味着

这个节目永远不应该停止

当驱动程序失败(这可能是致命的执行器失败的结果)被包含并且驱动程序可以正常退出时,流本身已经消失了。因此,您的代码将退出,因为没有更多的流可以运行

如果问题代码在您的控制下,则应将异常处理委托给任务,但如果是第三方代码,则没有此类选项


相反,在将问题记录传递给
saveToCassandra

之前,您应该验证您的数据并删除这些记录。要了解故障的来源,您必须承认
DStream功能。saveToCassandra
与一般的
DStream
输出操作一样,从严格意义上讲不是一个操作。实际上:

:

将函数应用于此数据流中的每个RDD。这是一个输出操作符,因此“This”数据流将被注册为一个输出流,并因此被物化

区别很微妙,但很重要——操作是注册的,但实际执行在不同的上下文中发生,在稍后的时间点

这意味着在调用
saveToCassandra
时不会捕获任何运行时故障

如前所述,
try
try
将包含驱动程序异常,如果直接应用于操作。例如,您可以将
saveToCassandra
重新实现为

dstream.foreachRDD(rdd => try { 
  rdd.sparkContext.runJob(rdd, writer.write _) 
} catch {
  case e: Exception => log.error("Error in saving data in Cassandra" + e. getMessage, e)
})
尽管当前批次将完全或部分丢失,但流应该能够继续

需要注意的是,这与捕获原始异常不同,原始异常将被抛出、取消捕获并在日志中可见。要从源代码捕获问题,您必须在writer中直接应用
try
/
catch
块,而这显然不是执行代码时的选项,您无法控制代码

外卖消息(已在此线程中声明)-确保清理数据以避免已知的故障源。

Th
dstream.foreachRDD(rdd => try { 
  rdd.sparkContext.runJob(rdd, writer.write _) 
} catch {
  case e: Exception => log.error("Error in saving data in Cassandra" + e. getMessage, e)
})