有没有一种方法可以根据大小刷新Kafka Streams WindowStore?

时间:2019-01-07 18:40:51

标签: apache-kafka-streams

我正在使用DSL API编写Kafka Streams应用程序,该API将读取kafka主题中的元组。在拓扑中,我要批处理元组。然后,如果(1)30秒过去了,或者(2)批处理的大小超过1 GB,那么我想将浴写入磁盘上的文件中。

我用TimeWindowedKStream编写的拓扑组元组。然后调用聚合并传递窗口存储。

我的问题是,当状态存储尝试写入Kafka ChangeLog时,我得到了

  

org.apache.kafka.common.errors.RecordTooLargeException

例外。

尤其是:

  

起因:org.apache.kafka.streams.errors.StreamsException:任务   [1_1]由于先前记录(键)捕获了错误,因此中止发送   \ x00 \ x00 \ x00 \ x06 \ x00 \ x00 \ x01h $ \ xE7 \ x88 \ x00 \ x00 \ x00 \ x00值   [B @ 419761c时间戳记1546807396524)   ibv2-capt-consumer-group-3-record-store-changelog由于   org.apache.kafka.common.errors.RecordTooLargeException:请求   包含大于服务器将允许的最大邮件大小的邮件   接受..

我曾尝试将CACHE_MAX_BYTES_BUFFERING_CONFIG设置为1MB,但由于文档指出此配置是否适用于整个拓扑。

这是我的拓扑

这是我一直在使用的Scala代码。请注意,我在这里使用kafka-streams-scala。

val builder = new StreamsBuilderS()

import com.lightbend.kafka.scala.streams.DefaultSerdes._

implicit val recordSerde = (new RecordSerde).asInstanceOf[Serde[Record]]
implicit val recordSeqSerde = (new RecordSeqSerde).asInstanceOf[Serde[RecordSeq]]

val inputStream: KStreamS[String, Record] = builder.stream[String,Record](topic)

val keyed = inputStream.selectKey[Int]((k,r) => random.nextInt(10)) 

val grouped: TimeWindowedKStreamS[Int, Record] = keyed.groupByKey.windowedBy(TimeWindows.of(TimeUnit.SECONDS.toMillis(30L)))

import org.apache.kafka.common.utils.Bytes

val windowedStore: Materialized[Int, RecordSeq, WindowStore[Bytes, Array[Byte]]] = Materialized
  .as[Int,RecordSeq,WindowStore[Bytes, Array[Byte]]]("record-store")
  .withKeySerde(integerSerde)
  .withValueSerde(recordSeqSerde)
  .withLoggingEnabled(ChangeLogConfig.getChangeLogConfig.asJava)  // increased max.request.size to 10 x default

val records: KTableS[Windowed[Int], RecordSeq] = grouped.aggregate(
  () => RecordSeq(Seq()),
  (randon: Int, record: Record, recordSeq: RecordSeq) => RecordSeq(recordSeq.records :+ record),
  windowedStore
)

val recordSeqStream: KStreamS[String, RecordSeq] = records.toStream((ws, r) => s"${ws.key()}-${ws.window().start()}-${ws.window().end()}")

recordSeqStream.foreach((k: String, rs: RecordSeq) => WrappedRecordFileWriter.write(k, rs))

注意:案例类RecordSeq(records:Seq [Record])

1 个答案:

答案 0 :(得分:1)

主题可以具有message.max.bytes属性中定义的最大大小的记录。这是代理可以接收并附加在主题中的最大消息大小。您的记录大小可能超过了该限制。因此,您需要更改此属性的配置以允许更大的记录大小。

可以在代理级别以及主题级别进行设置。您可以在此处参考更多详细信息:

http://kafka.apache.org/documentation/#brokerconfigs

http://kafka.apache.org/documentation/#topicconfigs