使用mapGroupState进行结构化流式传输会导致GC和性能问题

时间:2018-09-27 13:13:34

标签: apache-spark apache-kafka garbage-collection spark-structured-streaming

在我们的应用程序中,我们结合使用结构化流和MapGroupWithState以及从Kafka中读取内容。

启动应用程序后,在初始批处理期间性能良好,如果我看到kafka lastProgress接近每秒65K。经过几批处理后,性能完全降低到每秒2000左右。

在MapGroupWithState函数中,基本上是在进行更新,并且正在与状态存储中的值进行比较(下面提供的代码段)。

卡夫卡的抵销数-100000

启动应用程序后,在初始批处理期间性能良好,如果我看到kafka lastProgress接近每秒65K。经过几批处理后,性能完全降低到每秒2000左右。

如果我们从执行程序之一中看到线程转储,那么除了来自Spark UI的阻塞线程之外,就没有其他可疑之处

Thread Count

Thread Block

以下执行者之一的GC统计信息

GC后没什么区别

Before GC

After GC

代码段

case class MonitoringEvent(InternalID: String, monStartTimestamp: Timestamp, EndTimestamp: Timestamp, Stream: String, ParentID: Option[String])


val df = spark.readStream.format("kafka")
      .option("kafka.bootstrap.servers", Config.uatKafkaUrl)
      .option("subscribe", Config.interBranchInputTopic)
      .option("startingOffsets", "earliest")
      .option("failOnDataLoss", "true")
      .option("maxOffsetsPerTrigger", "100000")
      .option("request.required.acks", "all")
      .load()
      .selectExpr("CAST(value AS STRING)")    


        val me: Dataset[MonitoringEvent] = df.select(from_json($"value", schema).as("data")).select($"data.*").as[MonitoringEvent]

        val IB =   me.groupByKey(x => (x.ParentID.getOrElse(x.InternalID)))
        .mapGroupsWithState(GroupStateTimeout.ProcessingTimeTimeout)(IBTransformer.mappingFunctionIB _)
        .flatMap(x => x)


    val IBStream = IB
      .select(to_json(struct($"*")).as("value"), $"InternalID".as("key"))
      .writeStream
      .format("kafka")
      .queryName("InterBranch_Events_KafkaWriter")
      .option("kafka.bootstrap.servers", Config.uatKafkaUrl)
      .option("topic", Config.interBranchTopicComplete)
      .option("checkpointLocation", Config.interBranchCheckPointDir)
      .outputMode("update")
      .start()



object IBTransformer extends Serializable {

  case class IBStateStore(InternalID: String, monStartTimestamp: Timestamp)

  def mappingFunctionIB(intrKey: String, intrValue: Iterator[MonitoringEvent], intrState: GroupState[IBStateStore]): Seq[MonitoringEvent] = {

    try {
      if (intrState.hasTimedOut) {
            intrState.remove()
               Seq.empty
      } else {

        val events = intrValue.toSeq
        if (events.map(_.Status).contains(Started)) {

           val tmp = events.filter(x => (x.Status == Started && x.InternalID == intrKey)).head
           val toStore = IBStateStore(tmp.InternalID, tmp.monStartTimestamp)
            intrState.update(toStore)
            intrState.setTimeoutDuration(1200000) 
        }
        val IB = events.filter(_.ParentID.isDefined)
        if (intrState.exists && IB.nonEmpty) {
          val startEvent = intrState.get
          val IBUpdate = IB.map {x => x.copy(InternalID = startEvent.InternalID, monStartTimestamp = startEvent.monStartTimestamp) }
          IBUpdate.foreach(id => intrState.update((IBStateStore(id.InternalID, id.monStartTimestamp)))) // updates the state with new IDs
          IBUpdate
        } else {
          Seq.empty
        }
      }
    }

    catch
    .
    .
    .       
  }
}

使用的执行者数量-8 Exector内存-8G 驱动程序内存-8G

我在spark提交脚本中提供的Java选项和内存

 --executor-memory 8G \
 --executor-cores 8 \
 --num-executors 4 \
 --driver-memory 8G \
--driver-java-options "-Dsun.security.krb5.debug=true -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Duser.timezone=UTC -Dconfig.file=configIB.conf -Dlog4j.configuration=IBprocessor.log4j.properties" \

尝试在Java选项中使用G1GC,但没有任何改进。我们持有的密钥也小于提供的大小,所以不确定哪里出了问题。

是否有任何改进性能并消除GC问题的建议?

0 个答案:

没有答案