Scala 执行的最佳方式是什么;“不是转型”;数据集元素中的操作

Scala 执行的最佳方式是什么;“不是转型”;数据集元素中的操作,scala,apache-spark,apache-spark-sql,spark-structured-streaming,Scala,Apache Spark,Apache Spark Sql,Spark Structured Streaming,spark刚刚推出,我正在寻找一种使用spark结构化流媒体在数据集的所有元素中执行操作的方法: 我知道这是一个特定的用例,我想要的是遍历Dataset的所有元素,对其执行操作,然后继续使用Dataset 例如: 我得到了val df=Dataset[Person],我希望能够做到以下几点: def execute(df: Dataset[Person]): Dataset[Person] = { df.foreach((p: Person) => { someHttpClient

spark刚刚推出,我正在寻找一种使用spark结构化流媒体在数据集的所有元素中执行操作的方法:

我知道这是一个特定的用例,我想要的是遍历Dataset的所有元素,对其执行操作,然后继续使用Dataset

例如:

我得到了
val df=Dataset[Person]
,我希望能够做到以下几点:

def execute(df: Dataset[Person]): Dataset[Person] = {
 df.foreach((p: Person) => {
   someHttpClient.doRequest(httpPostRequest(p.asString)) // this is pseudo code / not compiling
 })
 df
}
不幸的是,
foreach
不适用于结构化流媒体,因为我遇到错误“流媒体源的查询必须使用writeStream.start执行”

我试图使用
map()
,但出现了错误“任务不可序列化”,我想这是因为http请求或http客户端不可序列化

我知道Spark主要用于过滤和转换,但有没有办法处理好这个特定的用例

谢谢:)

在得出解决方案是否存在的结论之前 让我们回答几个问题

Spark流媒体是如何工作的? Spark Streaming从输入源接收实时输入数据流,并将数据分为若干批,然后由Spark引擎进行处理,最后的批处理结果向下推送到下游应用程序

批处理执行是如何开始的? Spark对应用于数据流的所有转换进行惰性评估。它将在操作上应用转换(即仅当您开始流上下文时)

注意:每批数据流包含多个分区(就像spark Batch作业的运行顺序一样,直到输入源停止生成数据)

因此,您可以使用如下自定义逻辑

dStream.foreachRDD(new VoidFunction[JavaRDD[Object]] {
  override def call(t: JavaRDD[Object]): Unit = {
    t.foreach(new VoidFunction[Object] {
      override def call(t: Object): Unit = {
        //pseudo code someHttpClient.doRequest(httpPostRequest(t.asString))
      }
    })
  }
})
但再次确保someHttpClient可序列化

您可以按如下所述创建该对象

dStream.foreachRDD(new VoidFunction[JavaRDD[Object]] {
      override def call(t: JavaRDD[Object]): Unit = {
        // create someHttpClient object
        t.foreach(new VoidFunction[Object] {
          override def call(t: Object): Unit = {
            //pseudo code someHttpClient.doRequest(httpPostRequest(t.asString))
          }
        })
      }
    })
与Spark结构化流媒体相关

import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.sql._;
import org.apache.spark.sql.streaming.StreamingQuery;
import org.apache.spark.sql.streaming.StreamingQuery
import java.util.Arrays;
import java.util.Iterator;

val spark = SparkSession
  .builder()
  .appName("example")
  .getOrCreate();

val lines = spark.readStream.format("socket").option("host", "localhost").option("port", 9999).load(); // this is example source load copied from spark-streaming doc

lines.foreach(new ForeachFunction[Row] {
  override def call(t: Row): Unit = {
    //someHttpClient.doRequest(httpPostRequest(p.asString))
       OR
    // create someHttpClient object here and use it to tackle serialization errors
  }
})

// Start running the query foreach and do mention downstream sink below/
val query = lines.writeStream.start
query.awaitTermination()
在得出解决方案是否存在的结论之前 让我们回答几个问题

Spark流媒体是如何工作的? Spark Streaming从输入源接收实时输入数据流,并将数据分为若干批,然后由Spark引擎进行处理,最后的批处理结果向下推送到下游应用程序

批处理执行是如何开始的? Spark对应用于数据流的所有转换进行惰性评估。它将在操作上应用转换(即仅当您开始流上下文时)

注意:每批数据流包含多个分区(就像spark Batch作业的运行顺序一样,直到输入源停止生成数据)

因此,您可以使用如下自定义逻辑

dStream.foreachRDD(new VoidFunction[JavaRDD[Object]] {
  override def call(t: JavaRDD[Object]): Unit = {
    t.foreach(new VoidFunction[Object] {
      override def call(t: Object): Unit = {
        //pseudo code someHttpClient.doRequest(httpPostRequest(t.asString))
      }
    })
  }
})
但再次确保someHttpClient可序列化

您可以按如下所述创建该对象

dStream.foreachRDD(new VoidFunction[JavaRDD[Object]] {
      override def call(t: JavaRDD[Object]): Unit = {
        // create someHttpClient object
        t.foreach(new VoidFunction[Object] {
          override def call(t: Object): Unit = {
            //pseudo code someHttpClient.doRequest(httpPostRequest(t.asString))
          }
        })
      }
    })
与Spark结构化流媒体相关

import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.sql._;
import org.apache.spark.sql.streaming.StreamingQuery;
import org.apache.spark.sql.streaming.StreamingQuery
import java.util.Arrays;
import java.util.Iterator;

val spark = SparkSession
  .builder()
  .appName("example")
  .getOrCreate();

val lines = spark.readStream.format("socket").option("host", "localhost").option("port", 9999).load(); // this is example source load copied from spark-streaming doc

lines.foreach(new ForeachFunction[Row] {
  override def call(t: Row): Unit = {
    //someHttpClient.doRequest(httpPostRequest(p.asString))
       OR
    // create someHttpClient object here and use it to tackle serialization errors
  }
})

// Start running the query foreach and do mention downstream sink below/
val query = lines.writeStream.start
query.awaitTermination()

当foreachbatch无法在Sp St中使用时,afaik foreach可用。当foreachbatch无法在Sp St中使用时,Stafaik foreach可用。与结构化流媒体部分不起作用有关。我收到了“必须使用writeStream.start执行流源查询”消息。这就是为什么我说foreach不符合结构化流媒体,评论不正确,我们的方法不同。我关注的是数据集上的那个,而不是DataStreamWriter…与结构化流媒体相关的部分在我这边不起作用。我收到了“必须使用writeStream.start执行流源查询”消息。这就是为什么我说foreach不符合结构化流媒体,评论不正确,我们的方法不同。我关注的是数据集上的那个,而不是数据流编写器。。。