Scala SparkContext.textFile能否与自定义接收器一起使用?
我正在尝试实现一个流式作业,该作业使用自定义接收器从SQS读取消息。每个消息都包含一个对S3文件的引用,然后我希望将其读取、解析并存储为ORC 以下是我目前掌握的代码:Scala SparkContext.textFile能否与自定义接收器一起使用?,scala,apache-spark,spark-streaming,Scala,Apache Spark,Spark Streaming,我正在尝试实现一个流式作业,该作业使用自定义接收器从SQS读取消息。每个消息都包含一个对S3文件的引用,然后我希望将其读取、解析并存储为ORC 以下是我目前掌握的代码: val sc = new SparkContext(conf) val streamContext = new StreamingContext(sc, Seconds(5)) val sqs = streamContext.receiverStream(new SQSReceiver("events-elb") .cre
val sc = new SparkContext(conf)
val streamContext = new StreamingContext(sc, Seconds(5))
val sqs = streamContext.receiverStream(new SQSReceiver("events-elb")
.credentials("accessKey", "secretKey")
.at(Regions.US_EAST_1)
.withTimeout(5))
val s3File = sqs.map(messages => {
val sqsMsg: JsValue = Json.parse(messages)
val s3Key = "s3://" +
Json.stringify(sqsMsg("Records")(0)("s3")("bucket")("name")).replace("\"", "") + "/" +
Json.stringify(sqsMsg("Records")(0)("s3")("object")("key")).replace("\"", "")
val rawLogs = sc.textFile(s3Key)
rawLogs
}).saveAsTextFiles("/tmp/output")
不幸的是,此操作失败,出现以下错误:
Caused by: java.io.NotSerializableException: org.apache.spark.SparkContext
Serialization stack:
- object not serializable (class: org.apache.spark.SparkContext, value: org.apache.spark.SparkContext@52fc5eb1)
- field (class: SparrowOrc$$anonfun$1, name: sc$1, type: class org.apache.spark.SparkContext)
- object (class SparrowOrc$$anonfun$1, <function1>)
at org.apache.spark.serializer.SerializationDebugger$.improveException(SerializationDebugger.scala:40)
at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:46)
at org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:100)
at org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:295)
原因:java.io.notserializableeexception:org.apache.spark.SparkContext
序列化堆栈:
-对象不可序列化(类:org.apache.spark.SparkContext,值:org.apache.spark)。SparkContext@52fc5eb1)
-字段(类:SparrowOrc$$anonfun$1,名称:sc$1,类型:class org.apache.spark.SparkContext)
-对象(类SparrowOrc$$anonfun$1,)
位于org.apache.spark.serializer.SerializationDebugger$.ImproveeException(SerializationDebugger.scala:40)
位于org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:46)
位于org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:100)
位于org.apache.spark.util.ClosureCleaner$.ensureSerializable(ClosureCleaner.scala:295)
这是一种不正确的sc.textFile
使用方法吗?如果是这样,我可以使用什么方法将从SQS接收到的每个文件路径转发到文件读取器进行处理
FWIW,val s3File
的类型为mappedDStream
为了进一步说明,我将它用作我的接收器:。否。这不正确,因为SparkContext是:
SparkContext
存在于驱动程序中(或者可以说构成驱动程序),并负责编排任务(用于Spark作业)
执行者很笨,因此只知道如何运行任务
Spark不是这样工作的,您越早接受该设计决策,就越能熟练地正确开发Spark应用程序
如果是这样,我可以使用什么方法将从SQS接收到的每个文件路径转发到文件读取器进行处理
这是我无法回答的,因为我从未开发过自定义接收器。事实上,我们不能在
映射
操作中使用sparkContext
,因为在一个阶段中转换的闭包是在执行器中运行的,在执行器中没有定义sparkContext
方法是将过程分为两部分:首先,我们使用现有的映射
计算文件,但在转换
操作中使用文本文件
:
val s3Keys = sqs.map(messages => {
val sqsMsg: JsValue = Json.parse(messages)
val s3Key = "s3://" +
Json.stringify(sqsMsg("Records")(0)("s3")("bucket")("name")).replace("\"", "") + "/" +
Json.stringify(sqsMsg("Records")(0)("s3")("object")("key")).replace("\"", "")
}
val files DStream = s3Keys.transform{keys =>
val fileKeys= keys.collect()
Val files = fileKeys.map(f=>
sparkContext.textFile(f))
sparkContext.union(files)
}
filesDStream.saveAsTextFiles(..)