RDDs सीरियल इंटरफ़ेस का विस्तार करते हैं , इसलिए यह ऐसा नहीं है जो आपके कार्य को विफल कर रहा है। अब इसका मतलब यह नहीं है कि आप RDD
स्पार्क के साथ अनुक्रम कर सकते हैं और बचेंNotSerializableException
स्पार्क एक वितरित कंप्यूटिंग इंजन है और इसका मुख्य अमूर्त एक लचीला वितरित डेटासेट ( RDD ) है, जिसे एक वितरित संग्रह के रूप में देखा जा सकता है। मूल रूप से, RDD के तत्वों को क्लस्टर के नोड्स में विभाजित किया जाता है, लेकिन स्पार्क इसे उपयोगकर्ता से दूर करता है, जिससे उपयोगकर्ता RDD (संग्रह) के साथ बातचीत करता है जैसे कि यह एक स्थानीय हो।
नहीं भी कई विवरण में प्राप्त करने के लिए, लेकिन जब आप एक RDD (पर विभिन्न परिवर्तनों को चलाने map
, flatMap
, filter
और अन्य), अपने परिवर्तन कोड (बंद) है:
- चालक नोड पर क्रमबद्ध,
- क्लस्टर में उपयुक्त नोड्स के लिए भेज दिया,
- deserialized,
- और अंत में नोड्स पर निष्पादित किया गया
आप निश्चित रूप से इसे स्थानीय रूप से (आपके उदाहरण के अनुसार) चला सकते हैं, लेकिन वे सभी चरण (नेटवर्क पर शिपिंग के अलावा) अभी भी होते हैं। [यह आपको उत्पादन पर तैनात होने से पहले ही किसी भी कीड़े को पकड़ने देता है]
आपके दूसरे मामले में क्या होता है कि आप एक विधि कह रहे हैं, testing
जो मानचित्र फ़ंक्शन के अंदर से कक्षा में परिभाषित है । स्पार्क यह देखता है कि और चूंकि विधियां अपने दम पर क्रमबद्ध नहीं की जा सकती हैं, स्पार्क पूरी testing
कक्षा को क्रमबद्ध करने की कोशिश करता है , ताकि कोड तब भी काम करेगा जब किसी अन्य जेवीएम में निष्पादित हो। आपके पास दो संभावनाएँ हैं:
या तो आप कक्षा परीक्षण को क्रमबद्ध बनाते हैं, इसलिए पूरे वर्ग को स्पार्क द्वारा क्रमबद्ध किया जा सकता है:
import org.apache.spark.{SparkContext,SparkConf}
object Spark {
val ctx = new SparkContext(new SparkConf().setAppName("test").setMaster("local[*]"))
}
object NOTworking extends App {
new Test().doIT
}
class Test extends java.io.Serializable {
val rddList = Spark.ctx.parallelize(List(1,2,3))
def doIT() = {
val after = rddList.map(someFunc)
after.collect().foreach(println)
}
def someFunc(a: Int) = a + 1
}
या आप someFunc
एक विधि के बजाय फ़ंक्शन करते हैं (फ़ंक्शन स्काला में ऑब्जेक्ट हैं), ताकि स्पार्क इसे क्रमबद्ध करने में सक्षम हो जाएगा:
import org.apache.spark.{SparkContext,SparkConf}
object Spark {
val ctx = new SparkContext(new SparkConf().setAppName("test").setMaster("local[*]"))
}
object NOTworking extends App {
new Test().doIT
}
class Test {
val rddList = Spark.ctx.parallelize(List(1,2,3))
def doIT() = {
val after = rddList.map(someFunc)
after.collect().foreach(println)
}
val someFunc = (a: Int) => a + 1
}
इसी तरह, लेकिन कक्षा क्रमांकन के साथ समान समस्या आपके लिए रुचि नहीं हो सकती है और आप इस स्पार्क शिखर सम्मेलन 2013 की प्रस्तुति में इस पर पढ़ सकते हैं ।
एक साइड नोट के रूप में, आप फिर rddList.map(someFunc(_))
से लिख सकते rddList.map(someFunc)
हैं, वे बिल्कुल समान हैं। आमतौर पर, दूसरा पसंद किया जाता है क्योंकि यह पढ़ने के लिए कम क्रिया और क्लीनर है।
EDIT (2015-03-15): SPARK-5307 ने SerializationDebugger पेश किया और स्पार्क 1.3.0 इसका उपयोग करने वाला पहला संस्करण है। यह क्रमांकन पथ को NotSerializableException में जोड़ता है । जब NotSerializableException का सामना होता है, तो डीबगर ऑब्जेक्ट के लिए पथ को खोजने के लिए ऑब्जेक्ट ग्राफ़ पर जाता है जिसे क्रमबद्ध नहीं किया जा सकता है, और ऑब्जेक्ट को खोजने के लिए उपयोगकर्ता की मदद करने के लिए जानकारी का निर्माण करता है।
ओपी के मामले में, यह वही है जो stdout को मुद्रित किया जाता है:
Serialization stack:
- object not serializable (class: testing, value: testing@2dfe2f00)
- field (class: testing$$anonfun$1, name: $outer, type: class testing)
- object (class testing$$anonfun$1, <function1>)