Kafka producer.send()由producer.close()停止

时间:2016-05-27 10:40:02

标签: scala apache-kafka kafka-producer-api

我正在尝试在名为" test"的kafka主题上发送字数统计问题(在spark-scala中)的输出。见下面的代码:

val Dstream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topicsSet)

val lines = Dstream.map(f => f._2)
val words = lines.flatMap(_.split(" "))
val wordCounts = words.map(x => (x, 1)).reduceByKey(_ + _)

wordCounts.foreachRDD(
      rdd => rdd.foreach(
        f =>
          {
            val sendProps = new Properties()
            sendProps.put("metadata.broker.list", brokers)
            sendProps.put("serializer.class", "kafka.serializer.StringEncoder")
            sendProps.put("producer.type", "async")

            val config = new ProducerConfig(sendProps)
            val producer = new Producer[String, String](config)
            producer.send(new KeyedMessage[String, String]"test", f._1 + " " +f._2))
            producer.close();

          })) 

问题是随机输出中缺少一些单词。我还注意到,如果我删除了声明

producer.close()

没有数据丢失。

这是否意味着 producer.close()在实际将数据放入缓冲区之前中断 producer.send(),因为该特定元组未被发送给消费者?如果是,我该如何关闭生产者而不会有数据丢失的风险?

以上是我最初的问题,并由Vale的答案解决。

现在,当我再次更改 producer.type 属性时 - 数据随机丢失。

sendProps.put("producer.type", "sync")

为了澄清 producer.send 正在运行我需要放在输出主题中的所有单词。但是,有些单词会丢失,并且不会显示在输出Kafka主题中。

1 个答案:

答案 0 :(得分:1)

这很奇怪。 close()方法应该等待send完成,这就是引入close(time)方法的原因:as you can see here
所以,我使用Java 7. rdd.foreach是否在每个分区内运行?或者它是否在每个元组上运行(我认为它在做什么)? 如果是后者,你能试试rdd.foreachPartition(refer to this)吗?因为你为每条线创建了一个生产者,我担心这可能会导致问题(虽然理论上它不应该)。