簡體   English   中英

try catch塊未捕獲異常

[英]Exception is not caught by the try catch block

我正在將DStream保存到Cassandra。 Cassandra中有一列具有map<text, text>數據類型的列。 Cassandra在Map中不支持null值,但是流中可能會出現空值。

如果出現問題,我添加了try catch ,但是盡管如此,程序仍然停止了,並且在日志中沒有看到錯誤消息:

   try {
      cassandraStream.saveToCassandra("table", "keyspace")
    } catch {
      case e: Exception => log.error("Error in saving data in Cassandra" + e.getMessage, e)
    }

例外

Caused by: java.lang.NullPointerException: Map values cannot be null
    at com.datastax.driver.core.TypeCodec$AbstractMapCodec.serialize(TypeCodec.java:2026)
    at com.datastax.driver.core.TypeCodec$AbstractMapCodec.serialize(TypeCodec.java:1909)
    at com.datastax.driver.core.AbstractData.set(AbstractData.java:530)
    at com.datastax.driver.core.AbstractData.set(AbstractData.java:536)
    at com.datastax.driver.core.BoundStatement.set(BoundStatement.java:870)
    at com.datastax.spark.connector.writer.BoundStatementBuilder.com$datastax$spark$connector$writer$BoundStatementBuilder$$bindColumnUnset(BoundStatementBuilder.scala:73)
    at com.datastax.spark.connector.writer.BoundStatementBuilder$$anonfun$6.apply(BoundStatementBuilder.scala:84)
    at com.datastax.spark.connector.writer.BoundStatementBuilder$$anonfun$6.apply(BoundStatementBuilder.scala:84)
    at com.datastax.spark.connector.writer.BoundStatementBuilder$$anonfun$bind$1.apply$mcVI$sp(BoundStatementBuilder.scala:106)
    at scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:160)
    at com.datastax.spark.connector.writer.BoundStatementBuilder.bind(BoundStatementBuilder.scala:101)
    at com.datastax.spark.connector.writer.GroupingBatchBuilder.next(GroupingBatchBuilder.scala:106)
    at com.datastax.spark.connector.writer.GroupingBatchBuilder.next(GroupingBatchBuilder.scala:31)
    at scala.collection.Iterator$class.foreach(Iterator.scala:893)
    at com.datastax.spark.connector.writer.GroupingBatchBuilder.foreach(GroupingBatchBuilder.scala:31)
    at com.datastax.spark.connector.writer.TableWriter$$anonfun$writeInternal$1.apply(TableWriter.scala:233)
    at com.datastax.spark.connector.writer.TableWriter$$anonfun$writeInternal$1.apply(TableWriter.scala:210)
    at com.datastax.spark.connector.cql.CassandraConnector$$anonfun$withSessionDo$1.apply(CassandraConnector.scala:112)
    at com.datastax.spark.connector.cql.CassandraConnector$$anonfun$withSessionDo$1.apply(CassandraConnector.scala:111)
    at com.datastax.spark.connector.cql.CassandraConnector.closeResourceAfterUse(CassandraConnector.scala:145)
    at com.datastax.spark.connector.cql.CassandraConnector.withSessionDo(CassandraConnector.scala:111)
    at com.datastax.spark.connector.writer.TableWriter.writeInternal(TableWriter.scala:210)
    at com.datastax.spark.connector.writer.TableWriter.insert(TableWriter.scala:197)
    at com.datastax.spark.connector.writer.TableWriter.write(TableWriter.scala:183)
    at com.datastax.spark.connector.streaming.DStreamFunctions$$anonfun$saveToCassandra$1$$anonfun$apply$1.apply(DStreamFunctions.scala:54)
    at com.datastax.spark.connector.streaming.DStreamFunctions$$anonfun$saveToCassandra$1$$anonfun$apply$1.apply(DStreamFunctions.scala:54)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:87)
    at org.apache.spark.scheduler.Task.run(Task.scala:109)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
    ... 3 more

我想知道為什么盡管有try / catch塊,但是程序卻停止了。 為什么未捕獲到異常?

要了解失敗的根源,您必須承認DStreamFunctions.saveToCassandraDStream輸出操作通常相同,從嚴格意義上講,這不是一個操作。 實際上, 它只是調用foreachRDD

 dstream.foreachRDD(rdd => rdd.sparkContext.runJob(rdd, writer.write _)) 

依次

將函數應用於此DStream中的每個RDD。 這是一個輸出運算符,因此“ this” DStream將被注冊為輸出流,並因此實現。

差異是微妙的,但很重要-操作已注冊,但實際執行發生在不同的上下文中,在稍后的時間點。

這意味着在調用saveToCassandra時不會出現運行時失敗。

如前所述,如果直接應用於動作,則tryTry將包含驅動程序異常。 因此,例如,您可以將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塊,這顯然不是您執行代碼時無法控制的選擇。

帶走消息是(已在此線程中聲明)-請確保清理數據以避免已知的故障源。

問題是您沒有捕獲到您認為自己有的異常。 您擁有的代碼將捕獲驅動程序異常,實際上,像這樣構造的代碼將做到這一點。

但是,這並不意味着

該程序永不停止。

雖然包含了因執行器致命故障而導致的驅動程序故障,並且驅動程序可以正常退出,但流本身已經消失了。 因此,您的代碼將退出,因為沒有更多的流可以運行。

如果有問題的代碼在您的控制之下,則應將異常處理委派給任務,但是對於第3方代碼,則沒有此類選項。

相反,您應該先驗證數據並刪除有問題的記錄,然后再將這些記錄傳遞給saveToCassandra

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM