我正在使用Spark Streaming从Kafka读取JSON字符串的DStream。我需要以JSON格式保存S3上的输入数据。这就是我这样做的方式,但是当批处理中的数据量大约为5Mb时,执行此代码需要很长时间。可以优化吗?
我需要将数据保存在JSON文件(*.json
)中,因为还有另一个程序使用这些文件并按如下方式读取它们:
var df = sqlContext.read.json("s3n://" + bucketNameData + "/" + directoryS3 + "/*.json")
因此,为了将RDD保存为sinlge JSON文件,我尝试了rdd.map(lambda x :json.loads(x))
.coalesce(1, shuffle=True).saveAsTextFile('examples/src/main/resources/demo.json')
,但它以一种荒谬的方式保存数据,据我所知,我希望以后能够将它们读作我在上面显示(从json文件中获取df
)。因此我切换到amazonS3Client
,但我觉得它可能会被优化。也许我应该将rdd
转换为DataFrame左右,然后以某种方式将其保存为JSON?
val mySet = ssc.sparkContext.broadcast(Map("metadataBrokerList"->metadataBrokerList,
"bucketNameData"->bucketNameData,
"bucketNameCode"->bucketNameCode))
dstreamdata.foreachRDD(rdd => {
if (!rdd.isEmpty()) {
rdd.foreachPartition { iter =>
val producer = UtilsTest.createProducer(mySet.value("metadataBrokerList"))
val amazonS3Client = UtilsTest.createS3()
iter.foreach { msg =>
if (msg.nonEmpty) {
// Save messages to S3
val CONTENT_TYPE = "application/json"
val fileContentBytes = msg.getBytes(StandardCharsets.UTF_8)
val fileInputStream = new ByteArrayInputStream(fileContentBytes)
val metadata = new ObjectMetadata()
metadata.setContentType(CONTENT_TYPE)
metadata.setContentLength(fileContentBytes.length)
val datetime = Calendar.getInstance.getTime
val formatter = new SimpleDateFormat("yyyy-MMM-dd-HH-mm-ss")
val setID = formatter.format(datetime)
val filePath = mySet.value("bucketNameData") + "/file_" + setID + ".json"
val putObjectRequest = new PutObjectRequest(mySet.value("bucketNameData"), filePath, fileInputStream, metadata)
amazonS3Client.putObject(putObjectRequest)
//---
答案 0 :(得分:0)
你的直接putObject()会更高效,因为通常用于提交工作的rename()中没有副本。在处理失败和重播工作时,您可能会遇到问题。
如果使用newHadooopRDD,可以使用提交算法2显着降低开销:
import os
import pyautogui, pyautoguiFix
mouseSpeed = 0.5
# click icon on memu desktop
pyautogui.moveTo(1271, 379, duration= mouseSpeed)
pyautoguiFix.click()