火花结构流动态串滤波器

时间:2018-06-18 09:41:10

标签: apache-spark spark-structured-streaming

我们正在尝试将动态过滤器用于结构化流应用程序。

假设我们遵循Spark结构化流应用程序的伪实现:

 
spark.readStream()
     .format("kafka")
     .option(...)
     ...
     .load()
     .filter(getFilter()) <-- dynamic staff - def filter(conditionExpr: String):
     .writeStream()
     .format("kafka")
     .option(.....)
     .start();

和getFilter返回字符串

String getFilter() {
   // dynamic staff to create expression
   return expression; // eg. "column = true";
}

当前版本的Spark有可能具有动态过滤条件吗?我的意思是getFilter()方法应该动态返回一个过滤条件(假设它每10分钟刷新一次)。我们试图研究广播变量,但不确定结构化流媒体是否支持这样的事情。

看来,一旦提交了作业的配置,就无法更新。作为部署,我们使用yarn

我们非常感谢您的每一个建议/选项。

修改 假设getFilter()返回:

(columnA = 1 AND columnB = true) OR customHiveUDF(columnC, 'input') != 'required' OR columnD > 8

10分钟后,我们可以进行小的改动(在第一次OR之前没有第一次表达),并且我们可能有一个新的表达式(columnA = 2),例如:

customHiveUDF(columnC, 'input') != 'required' OR columnD > 10 OR columnA = 2

目标是为一个spark应用程序提供多个过滤器,而不是提交多个作业。

2 个答案:

答案 0 :(得分:1)

这里的广播变量应该没问题。您可以编写类似的过滤器,如:

query.filter(x => x > bv.value).writeStream(...)

其中bv是Broadcast变量。您可以按照此处所述进行更新:How can I update a broadcast variable in spark streaming?

其他解决方案是提供即RCP或RESTful端点,并每10分钟询问一次此端点。例如(Java,因为这里更简单):

class EndpointProxy {

     Configuration lastValue;
     long lastUpdated
     public static Configuration getConfiguration (){

          if (lastUpdated + refreshRate > System.currentTimeMillis()){
               lastUpdated = System.currentTimeMillis();
               lastValue = askMyAPI();
          }
          return lastValue;
     }
}


query.filter (x => x > EndpointProxy.getConfiguration().getX()).writeStream()

编辑:针对用户问题的hacky解决方法:

您可以创建1行视图:     // confsDF应该在一些驱动程序端单例中     var confsDF = Seq(某些内容).toDF(&#34; someColumn&#34;)

and then use:
query.crossJoin(confsDF.as("conf")) // cross join as we have only 1 value 
      .filter("hiveUDF(conf.someColumn)")
      .writeStream()...

 new Thread() {
     confsDF = Seq(some new data).toDF("someColumn)
 }.start();

这个hack依赖于Spark默认执行模型 - 微博。在每个触发器中,正在重建查询,因此应该考虑新数据。

你也可以在线程中执行:

Seq(some new data).toDF("someColumn).createOrReplaceTempView("conf")

然后在查询中:

.crossJoin(spark.table("conf"))

两者都应该有用。请记住,它不能使用连续处理模式

答案 1 :(得分:0)

这是简单的例子,其中我是动态过滤来自套接字的记录。而不是Date,您可以使用任何可以动态更新过滤器的rest API或轻量级zookeeper实例。

注意: - 如果您计划使用任何其他API或zookeeper或任何其他选项,请使用mapPartition而不是filter,因为在这种情况下,您可以为分区调用一次API / Connection。 / p>

val lines = spark.readStream
  .format("socket")
  .option("host", "localhost")
  .option("port", 9999)
  .load()

// Split the lines into words
val words = lines.as[String].filter(_ == new java.util.Date().getMinutes.toString)

// Generate running word count
val wordCounts = words.groupBy("value").count()

val query = wordCounts.writeStream
  .outputMode("complete")
  .format("console")
  .start()

query.awaitTermination()