如何在没有foreachRDD的情况下在JavaPairDStream中countByKey?

时间:2016-06-19 17:18:59

标签: apache-spark spark-streaming

这可能是一个非常微不足道的问题,但我不知道出了什么问题。

我有一个JavaPairDStream,并且对于每个批处理间隔,我想在流中获取RDD中的键数,以便稍后我可以在应用程序中使用此数字。

问题是,我可以通过以下方式获得密钥数量:

streamGiveKey.foreachRDD(new Function<JavaPairRDD<String, String>, Void>() {
        @Override
        public Void call(JavaPairRDD<String, String> stringStringJavaPairRDD) throws Exception {
            int a= stringStringJavaPairRDD.countByKey().size();
            countPartitions=a;

            System.out.print(a + "\r\n");
            return null;
        }
    });

JavaPairDStream<String,Iterable<String>>groupingEachBoilerValues= streamGiveKey.groupByKey(countPartitions);

其中countPartitions是一个全局变量,用于存储一个批处理间隔的键数。

问题是,应用程序永远不会到达groupingEachBoilerValues,它只会在forEachRDD中无限循环地打印。

我还有另一种方式吗? 非常感谢你。

1 个答案:

答案 0 :(得分:1)

您可以在驱动程序中保留全局计数。在这里

long globalCount = 0L;

 .. foreachRDD( 
      ..  globalCount += rdd.count();

此globalCount变量将驻留在驱动程序中,并将在每批次后继续更新。

更新怀疑论者啊!以上代码特定于流式传输。我很清楚它不适用于标准的非流式RDD代码。

我创建了包含上述方法的测试代码,并且计数器工作正常。将在几分钟内发布此代码。

import org.apache.spark._
import org.apache.spark.streaming._
var globalCount = 0L
val ssc = new StreamingContext(sc, Seconds(4))
val lines = ssc.socketTextStream("localhost", 19999)
val words = lines.flatMap(_.split(" "))
val pairs = words.map(word => (word, 1))
val wordCounts = pairs.reduceByKey(_ + _)
wordCounts.print()
lines.count().foreachRDD(rdd => { globalCount += rdd.count; println(globalCount) } )
ssc.start
ssc.awaitTermination

这里正在运行

scala> ssc.awaitTermination
-------------------------------------------
Time: 1466366660000 ms
-------------------------------------------

1
-------------------------------------------
Time: 1466366664000 ms
-------------------------------------------

2
-------------------------------------------
Time: 1466366668000 ms
-------------------------------------------

3

这是一个微小的数据生成器程序,用于测试:

import java.net._
import java.io._
case class ClientThread(sock: Socket) {
  new Thread() {
   override def run() {
      val bos = new BufferedOutputStream(sock.getOutputStream)
      while (true) {
          bos.write(s"Hello there it is ${new java.util.Date().toString}\n".getBytes)
          Thread.sleep(3000)
      }
   }
   }.start
 }
val ssock = new ServerSocket(19999)
while (true) {
  val sock =  ssock.accept()
  ClientThread(sock)
 }