【Spark】Spark執行報錯Task not serializable
文章目錄
異常資訊
org.apache.spark.SparkException: Task not serializable
Caused by: java.io.NotSerializableException:
出現場景
跑Spark程式的時候有可能會出現。
執行RDD行為的時候,map、filter等的方法使用了外部的變數,但是這個變數沒有或者不能序列化
以前接手專案沒發現這個Exception,這次自己寫單元測試反而跑出來了
在我寫【Spark】RDD開發手冊(JavaAPI函數語言程式設計)單元測試的時候發現的。
自推薦一下:
【Spark】RDD開發手冊(JavaAPI函數語言程式設計)
https://blog.csdn.net/HuHui_/article/details/83905308
解決方案
- 方案1:
注意小坑:Java的 @Transient 註解是方法級別的,不是變數級別。所以不要想著@Transient放在 sparkContext頭上…
/**
* 類首先要序列化
* @since hui_project 1.0.0
*/
public class TransformationRDDTest implements Serializable
/**
* sparkContext 和 SparkConf 要加上 transient
* @since hui_project 1.0.0
*/
private transient JavaSparkContext sparkContext;
private transient SparkConf sparkConf;
/**
* 外部引用的方法加上@Transient
* @since hui_project 1.0.0
*/
@Transient
private Iterator<Tuple2<Integer, Integer>> getSquare(Iterator<Integer> it) {}
- 方案2:
/**
* 類首先要序列化
* @since hui_project 1.0.0
*/
public class TransformationRDDTest implements Serializable
/**
* 外部引用的方法用static
* @since hui_project 1.0.0
*/
private static Iterator<Tuple2<Integer, Integer>> getSquare(Iterator<Integer> it) {}
- 方案3:
sparkConf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer");
分析
這裡我也是通過查資料,找到各種方法,很多我嘗試後沒成功。也有大部分是針對的Scala的,沒有說的太清楚解決方案和針對java怎麼解決。
不過其實這跟scala和java關係不大,我把搜尋引擎找到的分析和資料做個小總結。
特別感謝這篇BLOG的博主:
https://blog.csdn.net/silentwolfyh/article/details/53187945
下面重點分析
在編寫Spark程式中,由於在map等運算元內部使用了外部定義的變數和函式,由於外部定義的變數和函式有可能不支援序列化,仍然會導致整個類序列化時出現問題,最終可能會出現Task未序列化問題。
引用了類的成員函式,會導致該類及所有成員都需要支援序列化。因此,對於使用了某類成員變數或函式的情形,首先該類需要序列化(Serializable),同時需要對某些不需要序列化的成員變數標記以避免為序列化造成影響。
程式設計建議
- 引用了類的成員函式或變數,對應的類需要做序列化處理
- 執行map等方法的時候,儘量不要在閉包內部直接引用成員函式或變數