Conteúdo de saída do DStream em Scala Apache Spark

abaixo do Código Spark não parece efectuar qualquer operação num ficheiro example.txt

val conf = new org.apache.spark.SparkConf()
  .setMaster("local")
  .setAppName("filter")
  .setSparkHome("C:\\spark\\spark-1.2.1-bin-hadoop2.4")
  .set("spark.executor.memory", "2g");

val ssc = new StreamingContext(conf, Seconds(1))
val dataFile: DStream[String] = ssc.textFileStream("C:\\example.txt")

dataFile.print()
ssc.start() // Start the computation
ssc.awaitTermination() // Wait for the computation to terminate
Estou a tentar imprimir os primeiros 10 elementos do ficheiro usando dataFile.print()

parte da produção gerada:

15/03/12 12:23:53 INFO JobScheduler: Started JobScheduler
15/03/12 12:23:54 INFO FileInputDStream: Finding new files took 105 ms
15/03/12 12:23:54 INFO FileInputDStream: New files at time 1426163034000 ms:

15/03/12 12:23:54 INFO JobScheduler: Added jobs for time 1426163034000 ms
15/03/12 12:23:54 INFO JobScheduler: Starting job streaming job 1426163034000 ms.0 from job set of time 1426163034000 ms
-------------------------------------------
Time: 1426163034000 ms
-------------------------------------------

15/03/12 12:23:54 INFO JobScheduler: Finished job streaming job 1426163034000 ms.0 from job set of time 1426163034000 ms
15/03/12 12:23:54 INFO JobScheduler: Total delay: 0.157 s for time 1426163034000 ms (execution: 0.006 s)
15/03/12 12:23:54 INFO FileInputDStream: Cleared 0 old files that were older than 1426162974000 ms: 
15/03/12 12:23:54 INFO ReceivedBlockTracker: Deleting batches ArrayBuffer()
15/03/12 12:23:55 INFO FileInputDStream: Finding new files took 2 ms
15/03/12 12:23:55 INFO FileInputDStream: New files at time 1426163035000 ms:

15/03/12 12:23:55 INFO JobScheduler: Added jobs for time 1426163035000 ms
15/03/12 12:23:55 INFO JobScheduler: Starting job streaming job 1426163035000 ms.0 from job set of time 1426163035000 ms
-------------------------------------------
Time: 1426163035000 ms
-------------------------------------------

15/03/12 12:23:55 INFO JobScheduler: Finished job streaming job 1426163035000 ms.0 from job set of time 1426163035000 ms
15/03/12 12:23:55 INFO JobScheduler: Total delay: 0.011 s for time 1426163035000 ms (execution: 0.001 s)
15/03/12 12:23:55 INFO MappedRDD: Removing RDD 1 from persistence list
15/03/12 12:23:55 INFO BlockManager: Removing RDD 1
15/03/12 12:23:55 INFO FileInputDStream: Cleared 0 old files that were older than 1426162975000 ms: 
15/03/12 12:23:55 INFO ReceivedBlockTracker: Deleting batches ArrayBuffer()
15/03/12 12:23:56 INFO FileInputDStream: Finding new files took 3 ms
15/03/12 12:23:56 INFO FileInputDStream: New files at time 1426163036000 ms:

example.txt é de formato:

gdaeicjdcg,194,155,98,107
jhbcfbdigg,73,20,122,172
ahdjfgccgd,28,47,40,178
afeidjjcef,105,164,37,53
afeiccfdeg,29,197,128,85
aegddbbcii,58,126,89,28
fjfdbfaeid,80,89,180,82

Como diz a documentação print:

/** * Imprimir os primeiros dez elementos de cada RDD gerado neste DStream. Isto é uma saída * operador, de modo que este DStream será registrado como um fluxo de saída e lá materializar. */

isto significa que 0 RDD foram gerados para este fluxo ? Usando o Apache Spark se quiser ver o conteúdo de RDD usaria a função coletar de RDD. Estes métodos são similares para fluxos ? Em resumo, como imprimir para consolar o conteúdo do Stream ?

actualização:

Código actualizado com base no comentário do @0x0FFF. http://spark.apache.org/docs/1.2.0/streaming-programming-guide.html não parece dar um exemplo de leitura do sistema de ficheiros local. E isto não é tão comum como usar Spark core, onde existem exemplos explícitos para ler dados de arquivo?

aqui está o código actualizado:

val conf = new org.apache.spark.SparkConf()
  .setMaster("local[2]")
  .setAppName("filter")
  .setSparkHome("C:\\spark\\spark-1.2.1-bin-hadoop2.4")
  .set("spark.executor.memory", "2g");

val ssc = new StreamingContext(conf, Seconds(1))
val dataFile: DStream[String] = ssc.textFileStream("file:///c:/data/")

dataFile.print()
ssc.start() // Start the computation
ssc.awaitTermination() // Wait for the computation to terminate

mas a saída é a mesma. Quando eu adiciono novos arquivos a c:\\data dir (que têm o mesmo formato que os arquivos de dados existentes) eles não são processados. Presumo que dataFile.print deva imprimir as primeiras 10 linhas para consola ?

actualização 2:

Talvez isto esteja relacionado com o facto de eu estar a correr este código no ambiente do Windows?

Author: blue-sky, 2015-03-12

2 answers

Você entendeu mal o uso de textFileStream. Aqui está a sua descrição da documentação Spark:

crie um fluxo de entrada que monitorize um sistema de ficheiros compatível com o Hadoop para novos ficheiros e os leia como ficheiros de texto (usando a chave como escrita longa, valor como texto e formato de entrada como TextInputFormat).

Então, primeiro, você deve passar o diretório, e segundo, este diretório deve estar disponível a partir do nó que executa o receptor, de modo que é melhor usar HDFS para este propósito. Entao quando você coloca um novo file neste diretório, Ele seria processado pela função print() e as primeiras 10 linhas seriam impressas para ele

Actualização:

O meu código:

[alex@sparkdemo tmp]$ pyspark --master local[2]
Python 2.6.6 (r266:84292, Nov 22 2013, 12:16:22) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Spark assembly has been built with Hive, including Datanucleus jars on classpath
s15/03/12 06:37:49 WARN Utils: Your hostname, sparkdemo resolves to a loopback address: 127.0.0.1; using 192.168.208.133 instead (on interface eth0)
15/03/12 06:37:49 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 1.2.0
      /_/

Using Python version 2.6.6 (r266:84292, Nov 22 2013 12:16:22)
SparkContext available as sc.
>>> from pyspark.streaming import StreamingContext
>>> ssc = StreamingContext(sc, 30)
>>> dataFile = ssc.textFileStream('file:///tmp')
>>> dataFile.pprint()
>>> ssc.start()
>>> ssc.awaitTermination()
-------------------------------------------
Time: 2015-03-12 06:40:30
-------------------------------------------

-------------------------------------------
Time: 2015-03-12 06:41:00
-------------------------------------------

-------------------------------------------
Time: 2015-03-12 06:41:30
-------------------------------------------
1 2 3
4 5 6
7 8 9

-------------------------------------------
Time: 2015-03-12 06:42:00
-------------------------------------------
 2
Author: 0x0FFF, 2015-03-12 13:44:12

Aqui está um receptor personalizado que eu escrevi que escuta dados em uma dada dir:

package receivers

import java.io.File
import org.apache.spark.{ SparkConf, Logging }
import org.apache.spark.storage.StorageLevel
import org.apache.spark.streaming.{ Seconds, StreamingContext }
import org.apache.spark.streaming.receiver.Receiver

class CustomReceiver(dir: String)
  extends Receiver[String](StorageLevel.MEMORY_AND_DISK_2) with Logging {

  def onStart() {
    // Start the thread that receives data over a connection
    new Thread("File Receiver") {
      override def run() { receive() }
    }.start()
  }

  def onStop() {
    // There is nothing much to do as the thread calling receive()
    // is designed to stop by itself isStopped() returns false
  }

  def recursiveListFiles(f: File): Array[File] = {
    val these = f.listFiles
    these ++ these.filter(_.isDirectory).flatMap(recursiveListFiles)
  }

  private def receive() {

    for (f <- recursiveListFiles(new File(dir))) {

      val source = scala.io.Source.fromFile(f)
      val lines = source.getLines
      store(lines)
      source.close()
      logInfo("Stopped receiving")
      restart("Trying to connect again")

    }
  }
}

Uma coisa que eu acho que estar ciente é que os arquivos precisam ser processados em um tempo que é batchDuration. No exemplo abaixo é definido para 10 segundos, mas se o tempo de processar arquivos pelo receptor exceder 10 segundos, então alguns arquivos de dados não serão processados. Estou aberto a correcções neste ponto.

Aqui está como o receptor personalizado é implementado:

val conf = new org.apache.spark.SparkConf()
  .setMaster("local[2]")
  .setAppName("filter")
  .setSparkHome("C:\\spark\\spark-1.2.1-bin-hadoop2.4")
  .set("spark.executor.memory", "2g");

val ssc = new StreamingContext(conf, Seconds(10))

val customReceiverStream: ReceiverInputDStream[String] = ssc.receiverStream(new CustomReceiver("C:\\data\\"))

customReceiverStream.print

customReceiverStream.foreachRDD(m => {
  println("size is " + m.collect.size)
})

ssc.start() // Start the computation
ssc.awaitTermination() // Wait for the computation to terminate

Mais informação em : http://spark.apache.org/docs/1.2.0/streaming-programming-guide.html & https://spark.apache.org/docs/1.2.0/streaming-custom-receivers.html

 0
Author: blue-sky, 2015-03-13 11:20:47