在Spark Streaming应用程序中,在Spark worker端创建一个带有模式的Dataframe

时间:2018-01-21 13:44:18

标签: pandas dataframe spark-streaming

我开发了一个火花流媒体应用程序,其中包含json字符串的数据流。

sc = SparkContext("local[*]", "appname")
sc.setLogLevel("WARN")
sqlContext = sql.SQLContext(sc)

#batch width in time
stream = StreamingContext(sc, 5)
stream.checkpoint("checkpoint")

# mqtt setup
brokerUrl = "tcp://localhost:1883"
topic = "test"

# mqtt stream
DS = MQTTUtils.createStream(stream, brokerUrl, topic)

# transform DStream to be able to read json as a dict
jsonDS = kvs.map(lambda v: json.loads(v))

#create SQL-like rows from the json 
sqlDS = jsonDS.map(lambda x: Row(a=x["a"], b=x["b"], c=x["c"], d=x["d"]))

#in each batch do something
sqlDS.foreachRDD(doSomething)

# run
stream.start()
stream.awaitTermination()

def doSomething(time,rdd):

   data = rdd.toDF().toPandas()

上面的代码按预期工作:我以字符串方式接收一些jsons,我可以将每个批处理转换为数据帧,同时将其转换为Pandas DataFrame。

到目前为止一切顺利。

如果我想向DataFrame添加不同的架构,则会出现问题。 方法toDF()在以下函数中假定为schema=NonesqlContext.createDataFrame(rdd, schema)

如果我尝试从sqlContext内部访问doSomething(),则很明显它未定义。如果我尝试使用全局变量使其可用,我会得到无法序列化的典型错误。

我还读过sqlContext只能在Spark Driver中使用而不能在worker中使用。

所以问题是:toDF()首先是如何工作的,因为它需要sqlContext?如何为其添加架构(希望不改变源代码)?

在驱动程序中创建DataFrame似乎不是一个选项,因为我无法将其序列化为worker。

也许我没有正确看到这一点。

提前多多感谢!

1 个答案:

答案 0 :(得分:0)

回答我自己的问题......

定义以下内容:

def getSparkSessionInstance(sparkConf):
if ("sparkSessionSingletonInstance" not in globals()):
    globals()["sparkSessionSingletonInstance"] = SparkSession \
        .builder \
        .config(conf=sparkConf) \
        .getOrCreate()
return globals()["sparkSessionSingletonInstance"]

然后从工人那里打来电话:

spark = getSparkSessionInstance(rdd.context.getConf())

取自DataFrame and SQL Operations