我有一个火花流式传输作业,它消耗来自kafka的数据,并在对每个数据进行一些处理后发送回kafka。 为此,我正在对数据进行一些地图操作,
val lines = KafkaUtils.createStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topicNameMap, StorageLevel.MEMORY_AND_DISK)
var ad = ""
val abc = lines.map(_._2).map { x =>
val jsonObj = new JSONObject(x)
val data = someMethod(schema, jsonObj)
data
}
然后我正在对它进行foreach操作,我没有收集所有数据给驱动程序,因为我想在执行程序本身内发送这些记录。
abc.foreachRDD(rdd => {
rdd.foreach { toSend =>
val producer = KafkaProducerUtils.getKafkaProducer(kafkaBrokers)
println("toSend---->" + toSend)
producer.send(new ProducerRecord[String, String](topicToSend, toSend))
}
我尝试使用此代码获取1405数据10秒钟,但完成这项工作大约需要2.5分钟。我知道创建KafkaProducer
代价很高,有没有其他方法可以减少处理时间。为了我的测试目的,我使用2个执行器,每个2核和1GM。
答案 0 :(得分:0)
经过大量搜索,我发现了这篇关于KafkaSink的文章。这将为您提供有效生成火花流中kafka数据的想法。
答案 1 :(得分:0)
处理此类消息的这种巨大延迟必须有几个原因:
问题可能在您的消费阶段。如果你使用“createStream”,至少,Spark的次要版本使用高级消费者实现,需要Zookeeper来存储属于特定组的消费者的偏移量。因此,我会检查此通信,因为在 commit 阶段可能需要花费太多时间。如果由于任何原因而逐一提交承诺,您的消费率可能会受损。首先,请检查一下。
由于写入日志记录到文件系统,还有另一个原因。虽然您的配置表明内存是磁盘,但您可以在Spark文档中看到:
效率:在第一种方法中实现零数据丢失需要将数据存储在Write Ahead Log中,这进一步复制了数据。这实际上是低效的,因为数据有效地被复制两次 - 一次由Kafka复制,第二次由Write Ahead Log复制。第二种方法消除了问题,因为没有接收器,因此不需要Write Ahead Logs。只要您有足够的Kafka保留,就可以从Kafka恢复消息
为了更好的消费率,我会改用createDirectStream。