从火花工作中收取卡夫卡需要花费太多时间

时间:2016-12-09 05:07:51

标签: scala apache-spark apache-kafka apache-spark-sql spark-streaming

我有一个火花流式传输作业,它消耗来自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。

2 个答案:

答案 0 :(得分:0)

经过大量搜索,我发现了这篇关于KafkaSink的文章。这将为您提供有效生成火花流中kafka数据的想法。

答案 1 :(得分:0)

处理此类消息的这种巨大延迟必须有几个原因:

  1. 问题可能在您的消费阶段。如果你使用“createStream”,至少,Spark的次要版本使用高级消费者实现,需要Zookeeper来存储属于特定组的消费者的偏移量。因此,我会检查此通信,因为在 commit 阶段可能需要花费太多时间。如果由于任何原因而逐一提交承诺,您的消费率可能会受损。首先,请检查一下。

  2. 由于写入日志记录到文件系统,还有另一个原因。虽然您的配置表明内存是磁盘,但您可以在Spark文档中看到:

  3.   

    效率:在第一种方法中实现零数据丢失需要将数据存储在Write Ahead Log中,这进一步复制了数据。这实际上是低效的,因为数据有效地被复制两次 - 一次由Kafka复制,第二次由Write Ahead Log复制。第二种方法消除了问题,因为没有接收器,因此不需要Write Ahead Logs。只要您有足够的Kafka保留,就可以从Kafka恢复消息

    为了更好的消费率,我会改用createDirectStream。