RDD'ler Serialisable arabirimini genişletir , bu nedenle görevinizin başarısız olmasına neden olan şey bu değildir. Bu, RDD
Spark ile serileştirebileceğiniz ve kaçınabileceğiniz anlamına gelmezNotSerializableException
Spark, dağıtılmış bir bilgi işlem motorudur ve ana soyutlaması, dağıtılmış bir koleksiyon olarak görüntülenebilen esnek bir dağıtılmış veri kümesidir ( RDD ). Temel olarak, RDD'nin öğeleri kümenin düğümleri arasında bölünür, ancak Spark bunu kullanıcıdan uzak tutar ve kullanıcının RDD (koleksiyon) ile yerel birmiş gibi etkileşim kurmasına izin verir.
Çok fazla detaya olsun, ancak bir RDD (farklı dönüşümleri yayınlandığında öyle değil map
, flatMap
, filter
ve diğerleri), sizin dönüşüm kodu (kapatma) 'dir:
- sürücü düğümünde serileştirilmiş,
- kümedeki uygun düğümlere gönderilir,
- serileştirilemezse,
- ve nihayet düğümlerde idam edildi
Elbette bunu yerel olarak çalıştırabilirsiniz (örneğin örnekte olduğu gibi), ancak tüm bu aşamalar (ağ üzerinden gönderim dışında) hala gerçekleşir. [Bu, üretime dağıtmadan önce bile hataları yakalamanızı sağlar]
İkinci durumunuzda olan şey testing
, harita işlevinin içinden sınıfta tanımlanan bir yöntemi çağırmanızdır . Spark bunu görür ve yöntemler kendi başına serileştirilemediğinden, Spark tüm testing
sınıfı serileştirmeye çalışır , böylece kod başka bir JVM'de yürütüldüğünde yine de çalışır. İki olasılığınız var:
Sınıf testini serileştirilebilir hale getirirsiniz, böylece tüm sınıf Spark tarafından serileştirilebilir:
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
}
veya someFunc
bir yöntem yerine işlev yaparsınız (işlevler Scala'daki nesnelerdir), böylece Spark bunu seri hale getirebilir:
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
}
Sınıf serileştirmesi ile benzer ancak aynı sorun sizi ilgilendirebilir ve bu Spark Summit 2013 sunumunda okuyabilirsiniz. .
Bir yan not olarak, yeniden yazabilirsiniz rddList.map(someFunc(_))
için rddList.map(someFunc)
onlar tam olarak aynıdır. Genellikle, daha az ayrıntılı ve okunması daha temiz olduğu için ikincisi tercih edilir.
DÜZENLEME (2015-03-15): SPARK-5307 , SerializationDebugger ve Spark 1.3.0'ı kullanan ilk sürümdür. NotSerializableException öğesine serileştirme yolu ekler . NotSerializableException ile karşılaşıldığında, hata ayıklayıcı, serileştirilemeyen nesneye giden yolu bulmak için nesne grafiğini ziyaret eder ve kullanıcının nesneyi bulmasına yardımcı olacak bilgileri oluşturur.
OP'nin durumunda, stdout'a yazdırılan şey budur:
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>)