Scala 我的spark结构化流式代码中是否存在一些缺陷,导致运行数小时后响应缓慢?

Scala 我的spark结构化流式代码中是否存在一些缺陷,导致运行数小时后响应缓慢?,scala,apache-spark,spark-streaming,Scala,Apache Spark,Spark Streaming,spark作业具有正确的功能和逻辑。然而,经过几个小时的运行,它变得越来越慢。下面的代码中是否存在一些陷阱 val query = "(select * from meta_table) as meta_data" val meta_schema = new StructType() .add("config_id", BooleanType) .add("threshold

spark作业具有正确的功能和逻辑。然而,经过几个小时的运行,它变得越来越慢。下面的代码中是否存在一些陷阱

val query = "(select * from meta_table) as meta_data"    
val meta_schema = new StructType()         
       .add("config_id", BooleanType)         
       .add("threshold", LongType)         
var meta_df = spark.read.jdbc(url, query, connectionProperties)         
var meta_df_explode=meta_df.select(col("id"), from_json(col("config"), meta_schema).as("config")).select("config_id", "thresold", "config.*")  

//rules_imsi_df: joining of kafka ingestion with the meta_df_explode 

//rules_monitoring_df: static dataframe for monitoring purpose   

val rules_monitoring_stream =        
            rules_imsi_df.writeStream           
                        .outputMode("append")  
                          .format("memory")
                        .trigger(Trigger.ProcessingTime("120  seconds"))
                         .foreachBatch {                  
                              (batchDF: DataFrame, batchId: Long) =>
                                    if(!batchDF.isEmpty)                                                     {    

printf("At %d, the microbatch has %d records \n", Instant.now.getEpochSecond, batchDF.count())                                                             
batchDF.show()                                                            
 batchDF.persist()                                                                var batchDF_group = batchDF.groupBy("id").sum("volume").withColumnRenamed("sum(volume)", "total_volume_id")                  
rules_monitoring_df = rules_monitoring_df.join(batchDF_group, rules_monitoring_df("id") === batchDF_group("id"), "left").select(rules_monitoring_df("id"), batchDF_group("total_volume_id")).na.fill(0)                         
rules_monitoring_df = rules_monitoring_df.withColumn("volume", rules_monitoring_df("volume")+rules_monitoring_df("total_volume_id"))                                                               batchDF.unpersist()                                                                          }                                          }.start()    


      while(rules_monitoring_stream.isActive)    {                  
Thread.sleep(240000)                      
... //Periodically load meta data from database          
meta_df = spark.read.jdbc(url, query, connectionProperties)              
meta_df_explode=meta_df.select(col("id"), from_json(col("config"), meta_schema).as("config")).select("config_id", "thresold", "config.*")         
} 


以下几点是我对上述代码的观察。如果我发现什么,我会加上

  • 删除
    格式(“内存”)
    ,因为它是为了调试而不是为了生产用例
  • 从代码中删除所有
    var
  • 不要将
    DataFrame
    分配回
    rules\u monitoring\u df
    内部
    foreachBatch
    ,因为此
    foreachBatch
    将由多个线程同时调用,您可能会得到错误的结果。相反,尝试将结果保存到hdfs或配置单元表中,并在需要时回读
  • 如果可能的话,尝试在代码下方移动到
    spark streaming listener
    ,避免在循环时出现额外的

  • 为什么要使用-
    .format(“内存”)
    ,它仅用于调试目的-
    这应用于低数据量上的调试目的,因为整个输出都收集并存储在驱动程序内存中。因此,请谨慎使用。
    谢谢Srinivas。好发现。是的,我忘了测试后取下了这个零件。除了这个问题,还有什么问题需要我注意吗?谢谢您能添加您的应用程序逻辑吗?您实际在做什么?谢谢。基本逻辑相当简单。我想在120秒的时间内流式传输卡夫卡数据,处理微批次数据,并填充一个静态数据帧(规则监控)。为了获得微博客,从卡夫卡摄取的数据将与元数据帧连接在一起,元数据帧定期从postgre数据库读取。微批次将通过将一些数据字段相加到静态数据帧中来累积。如果满足某些条件,while循环中还有一些逻辑可以重置静态数据帧中的一些行。谢谢,伙计,这非常有用!我会根据你的意见进一步改进。还有一个问题。在我的用例中,我需要更新foreachBatch中rules_monitoring_df中的现有记录,而不仅仅是插入新记录。保存到蜂箱表中是一个好主意。spark sql现在支持更新配置单元表中的记录吗?我在spark 2.4.0中尝试了这种方法,发现不支持update语句。对于这个案例,什么是最好的解决办法?谢谢您将在何处以及如何使用来自
    rules\u monitoring\u df
    dataframe的数据?我的意思是,除了while循环中的
    foreachBatch
    函数外,如果满足某些条件,我还将使用它写入postgresql表。此外,在某些情况下,此数据帧的某些行将被重置。此外,我试图删除格式(内存)。它现在不显示OOM问题。但是,在运行几个小时后,它会生成一个节点不正常错误。“1/2本地目录不正确:/mnt/thread;1/1日志目录不正确:/var/log/hadoop-thread/containers”内部循环代码,您可以移动到内部查询进度侦听器。。因为此代码不依赖于数据帧
    while(rules_monitoring_stream.isActive)    {                  
    Thread.sleep(240000)                      
    ... //Periodically load meta data from database          
    meta_df = spark.read.jdbc(url, query, connectionProperties)              
    meta_df_explode=meta_df.select(col("id"), from_json(col("config"), meta_schema).as("config")).select("config_id", "thresold", "config.*")         
    }