Download - Meetup Real Time Aggregations Spark Streaming + Spark Sql

Transcript
Page 1: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

22 Marzo 2016

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

Page 2: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

Quienes somos

Conoce a algunos de ellos en gitHub https://github.com/Stratio/Sparta/graphs/contributors

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

José Carlos García Serrano

Arquitecto Big Data en Stratio.

Amante de las nuevas tecnologías y de las arquitecturas basadas en Big Data.

FanBoy de Scala, Spark, Akka, MongoDB y Cassandra.

Y como no… de Stratio Sparta y Stratio Crossdata.

El equipo de SPARTA:

Page 3: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

José Carlos García SerranoArquitecto Big [email protected]

CONTACTO

ÍNDICE

INTRODUCCIÓN SPARTA

• Arquitectura

• Tecnologías

1 2 3INPUTS

• Receiver WebSocket

• Receiver RabbitMq

• Receiver avanzados

• Spark Streaming HA

STREAMING - JVM

• Problemas y Recomendaciones

• Stratio JobServer

• Cluster Managers

OUTPUTS

• Transformaciones

• DataFrames

• API DataSources

Vs Tu Código

• Triggers

4 5 6OPERACIONES AVANZADAS DE STREAMING

• Stateful

• Optimizando Rendimiento

DEMO TIME

Page 4: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

STRATIO SPARTA1INTRODUCCIÓN

Page 5: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

1. INTRODUCCIÓN SPARTA > ARQUITECTURA

Page 6: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

1. INTRODUCCIÓN SPARTA > TECNOLOGÍAS

Page 7: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

1. INTRODUCCIÓN SPARTA > TECNOLOGÍAS

SCALA - AKKA - SPARK TODOS BAILAN JUNTOS

Page 8: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

INPUTS

REAL TIME

AGGREGATION ENGINE:

SPARK STREAMING +

SPARK SQL

2

Page 9: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

2.1 Receiver WebSocket

• Spark nos deja abierta una API para poder desarrollar receptores de datos para nuestros procesos de Streaming.

• En Sparta hemos desarrollado uno básico para poder conectarnos a webSockets.

• Implementando nuestra abstract class Input del SDK lo tenemos incorporado en nuestro Engine!!

• Tenemos dos opciones para poder guardar datos en un batch de streaming:

Implementando una clase abstracta Receiver

Extendiendo dentro de un Actor el trait ActorHelper

2 INPUTS

ASÍ DE FÁCIL PODEMOS EXTENDER LA

FUNCIONALIDAD QUE SPARK NOS OFRECE

Page 10: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

2 INPUTS > WEBSOCKET RECEIVER

class MyReceiver(storageLevel: StorageLevel) extends Receiver[String](storageLevel) {

def onStart() {

//Store()

}

def onStop() {

}

}

ssc.receiverStream(new MyReceiver(storageLevel(sparkStorageLevel)))

class MyActor extends Actor with ActorHelper{

def receive {

case anything: String => store(anything)

}

}

ssc.actorStream[String](Props(new MyActor),"MyActorReceiver")

SPARK SDK

Page 11: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

2 INPUTS > WEBSOCKET RECEIVER

abstract class Input(properties: Map[String, Any]) extends Parameterizable(properties) {

def setUp(ssc: StreamingContext, storageLevel: String): DStream[Row]

}

SPARTA INPUT SDK

FÁCIL VERDAD??

VEAMOS EL WEBSOCKET RECEIVER

Page 12: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

2.2 Receiver RabbitMQ

• Spark Packages es un repositorio de proyectos que extienden el SDK de Spark para ofrecernos más funcionalidad.

• En Sparta hemos contribuido desarrollando el receiver de RabbitMQ

• En un principio era una clase más de nuestro Input de RabbitMQ, ahora es un repositorio externo en GitHub y por supuesto Open Source.

2 INPUTS

VEÁMOS UN RECEIVER UN POCO MÁS AVANZADO

RABBITMQ

Page 13: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

2.3 Receivers Avanzados

• Spark Streaming crea un Receiver en un executor de Spark, este recibe los datos y luego son distribuidos por el cluster.

• El Receiver de KafkaDirect de Spark es Distribuido y capaz de hacer que cada Executor reciba una porción de datos, cada uno de ellos mantiene un offset de donde va leyendo en Kafka.

• El clásico receiver de Kafka y el resto de receivers de Spark No son Distribuidos, si queremos paralelizar hay que hacer DStream.union(otherDStream).

• Hay que intentar hacer los Receiver Fault Tolerance, debemos llamar a la función “store(múltiples eventos)” pasandole un iterador, después deberíamos esperar un Ack según el StorageLevel seleccionado. Debemos controlar las políticas de reconexión en nuestro Custom Receiver.

Performance WriteAheadLogs!! más de un receiver y no controlar el StorageLevel!!

2 INPUTS

Page 14: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

2.4 Spark Streaming HA

2 INPUTS

Post recomendado!

Page 15: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

STREAMING - JVM

REAL TIME

AGGREGATION ENGINE:

SPARK STREAMING +

SPARK SQL

3

Page 16: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

3.1 Problemas y Recomendaciones I

• Solamente podemos tener un SparkContext y un StreamingContext corriendo en una JVM. Mínimo dos cores!!

• Si no creamos correctamente el Spark Streaming Context siguiendo la recomendación de Spark, no podemos tener nuestro sistema Fault Tolerance.

• Si hacemos nuestro streaming Fault Tolerance o usamos transformaciones stateful debemos activar el checkpointing.

• Debemos crear los contextos correctamente:

SparkContext.getOrCreate()

SparkSQLContext.getOrCreate()

SparkStreamingContext.getOrCreate({func}, checkpointPath) ← Fault Tolerance, necesita checkpoint

3 STREAMING - JVM

Page 17: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

3.1 Problemas y Recomendaciones II

• Es recomendable parar el StreamingContext mediante el método stop utilizando el parámetro gracefully.

• Cuando un SparkContext es cerrado, tendremos problemas al volver a crear uno.

• Los Tests de integración que comparten la JVM, pueden tener problemas con los contextos de Spark.

• Cuidado con los Closures y los problemas de Serialización. Los object de Scala son nuestros amigos, pero con mesura!

3 STREAMING - JVM

Page 18: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

3 STREAMING - JVM > STRATIO JOBSERVER

SPARTA COMO UN SERVIDOR DE JOBS DE STREAMING

SPARTA DRIVER

CLUSTER MANAGER

SPARK DRIVER

SPARK DRIVER

SPARK DRIVER

Receiver

Executor

Receiver

Executor

Receiver

Executor

Job 1

Job 2

Job N

Submit Job 1

Submit Job 2

Submit Job N

Tasks

Tasks

TasksActores de Akka coordinan la ejecución de Jobs que contienen contextos de Spark.

Sparta en modo cluster genera un Spark-Submit al cluster manager que tengamos seleccionado.

Cada Spark Driver se ejecuta en un Worker y tiene su propia JVM.

Page 19: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

3 STREAMING - JVM > CLUSTER MANAGERS

SPARTA EJECUTA EN YARN, MESOS Y STANDALONE

CLUSTER MANAGER

SPARK DRIVER

ReceiverSubmit Job Jobs

Yarn, Mesos y StandAlone tienen propiedades específicas

para realizar el Submit.Número de cores y memoria que tendrá el driver y los Executors.

Sparta por defecto lanza los trabajos de Spark en modo cluster

sobre Yarn y Mesos.

El sistema de ejecución de Fine-Grained de Mesos y Dynamic

Resource Allocation de Yarn no está recomendado para procesos

de Streaming. Usar Coarse Grained.

Worker

Executors

Tasks

Para poder tener comunicación con los jobs que se ejecutan en el

cluster de Spark, Sparta usa Zookeeper.

Nos aislamos de las API’s de cada cluster manager, gracias a

Listeners de Curator dentro de Actores de Akka.

La comunicación es bidireccional, por lo que podemos mandar

desde el driver de Sparta mensajes a los Jobs del Cluster.

Cuando un Receiver se cae, Spark levanta otro, si tenemos el

Checkpoint activado es Fault Tolerance

Cualquier Jar que necesitemos debemos subirlo a HDFS o pasar

la ruta local y pasarlo como parámetro a Spark-Submit.

Si la ejecución es sobre Mesos, no funcionan correctamente las

rutas locales y las de HDFS, debemos bajarlo en el Driver de

Spark y añadirlo al Classpath y al SparkContext.

Page 20: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

OUTPUTS

REAL TIME

AGGREGATION ENGINE:

SPARK STREAMING +

SPARK SQL

4

Page 21: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

4.1 Transformaciones

Cuando trabajamos con DStream[T] podemos aplicar transformaciones como .map o .flatMap para modificar el contenido del DStream y pasar del tipo T a una Clase de Scala.

Imaginad que nuestro String es un JSON, podemos hacer cosas como esta:

Todo esto es aplicable también a los RDD[T] de Spark.

4 OUTPUTS

val parsedDStream: DStream[Row] = originalDStream.map(data =>

Row(JSON.parseFull(data).get.asInstanceOf[Map[String, Any]].values))

val originalDStream: DStream[String]

val parsedDStream: DStream[Int] = originalDStream.map(data => Row(data))

Page 22: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

4.2 DataFrames

En Sparta hemos decidido generar un tipo de dato genérico para todas las entradas y salidas de cada uno de los componentes del SDK.

Nuestro tipo genérico es la clase Row de Spark, de esta forma podemos generar DataFrames aplicando un Schema en cualquier momento. Un DataFrame puede ser guardado por cualquiera de nuestros outputs con la función upsert.

4 OUTPUTS

val schema: StructType

val output: Output

val parsedDStream: DStream[Row]

parsedDStream.foreachRDD(rdd =>

val parsedDataFrame = SQLContext.getOrCreate(rdd.context).createDataFrame(rdd, schema)

output.upsert(parsedDataFrame, dataFrameOptions)

)

Page 23: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

4 OUTPUTS > DATAFRAMES

abstract class Output(

keyName: String,

version: Option[Int],

properties: Map[String, JSerializable],

schemas: Seq[TableSchema]

) extends Parameterizable(properties) with Logging {

def setup(options: Map[String, String] = Map.empty[String, String]): Unit = {}

def upsert(dataFrame: DataFrame, options: Map[String, String]): Unit

}

SPARTA OUTPUT SDK

Page 24: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

4.3 API DataSource Spark vs Tú Código

Los Outputs de Sparta trabajan con DataFrames, un dataframe puede ser persistido de múltiples formas, veamos dos de ellas:

API DataSource de Spark

Tu código usando la librería de Java o Scala

4 OUTPUTS

dataFrame.write.format(MongoDbSparkDatasource) .mode(Append) .options(dataFrameOptions).save()

dataFrame.foreachPartition{ rowList =>

rowList.foreach{ row =>

saveMethod(row)

}

}

Page 25: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

4.4 Triggers

Gracias a nuestro tipo genérico Row y a Spark SQL hemos podido generar consultas SQL sobre el stream de datos, que puede ser guardado en cualquiera de nuestros Outputs.

Esta funcionalidad puede ser usada para generar Streaming ETL, enriquecimiento, alertas, agregaciones, etc...

4 OUTPUTS

dataFrame.registerTempTable(inputTableName)

val queryDataFrame = sqlContext.sql(trigger.sql)

INPUT TRANSFORMATIONS

CUBES

STREAM TRIGGER

CUBE TRIGGERS

Post-Agregaciones y Alertas sobre los datos agregados por el Cube

“select * from cube where count > 30”Inyección de sentencias SQL sobre el Stream de datos.

“select * from stream”

Page 26: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

OPERACIONES AVANZADAS DE STREAMING

REAL TIME

AGGREGATION ENGINE:

SPARK STREAMING +

SPARK SQL

5

Page 27: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

5.1 Stateful

Cuando trabajamos con DStreams podemos pasar de tener un DStream a tener una secuencia de DStreams:

● Secuencia de elementos que determinan la configuración de una operación de Streaming con ventana de tiempo y ventana de procesado.

● Podemos hacer un map sobre nuestra lista y por cada elemento podemos hacer transformaciones sobre el DStream según los parámetros de nuestra clase.

● El resultado es una lista de DStreams para trabajar con ellos en conjunto… foreachRDD, DataFrames, Save, Joins, etc...

5 OP. AVANZADAS DE STREAMING

val elements: Seq[MyConfigurationClass]

val originalDStream: DStream[Row]

val listOfDStream: Seq[DStream[Row]] = elements.map(element =>

originalDStream.window(element.window, element.slidingWindow))

Page 28: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

Hasta ahora conocemos las dos operaciones que mantienen estados: UpdateStateByKey y ReduceByKeyAndWindow

5 OP. AVANZADAS DE STREAMING > STATEFUL

def updateStateByKey[S: ClassTag](

updateFunc: (Seq[V], Option[S]) => Option[S]

): DStream[(K, S)] = ssc.withScope {

updateStateByKey(updateFunc, defaultPartitioner())

}

Queremos ir más allá …

Page 29: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

UpdateStateByKey

Spark en el método compute del StateDStream tiene algo que podíamos esperar:

Esta función genera siempre un único RDD dentro del DStream y hace el checkpointing automáticamente.

5 OP. AVANZADAS DE STREAMING > STATEFUL

def updateStateByKey[S: ClassTag](

updateFunc: (Iterator[(K, Seq[V], Option[S])]) => Iterator[(K, S)],

partitioner: Partitioner,

rememberPartitioner: Boolean

): DStream[(K, S)] = ssc.withScope {

new StateDStream(self, ssc.sc.clean(updateFunc), partitioner, rememberPartitioner, None)

}

val stateRDD = prevStateRDD.mapPartitions(finalFunc, preservePartitioning)

Esta función es la que realiza la modificación del estado según la Key

Page 30: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

En resumen

● Caducamos los datos filtrando el Iterator.

● Controlamos el Partitioner y podemos hacer que se preserve. (mapPartitions)

● Sabemos en cada Batch cuando tenemos datos nuevos y cuando no:

○ Conservamos el mismo estado

○ Resetear, filtrar, etc…

5 OP. AVANZADAS DE STREAMING > STATEFUL

El futuro

● Spark 1.6 MapWithState

● Kafka Streams y Kafka Connect

● Spark 2.0 :

Streaming Queries y Stateful Queries with DataFrames

Triggers

Kafka sink SQL

Agregaciones continuas sobre streaming

Page 31: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

Cube de SPARTA

5 OP. AVANZADAS DE STREAMING > STATEFUL

protected def updateAssociativeState(dimensionsValues: DStream[(DimensionValuesTime, AggregationsValues)])

: DStream[(DimensionValuesTime, MeasuresValues)] = {

val newUpdateFunc = expiringDataConfig match {

case None => updateFuncAssociativeWithoutTime

case Some(_) => updateFuncAssociativeWithTime

}

val valuesCheckpointed = dimensionsValues.updateStateByKey(

newUpdateFunc,

new HashPartitioner(dimensionsValues.context.sparkContext.defaultParallelism),

rememberPartitioner

)

filterUpdatedMeasures(valuesCheckpointed)

En base a la configuración ejecutamos una función de agregación determinada

El DStream resultante es asignado a una variable que puede es la entrada de otra función

Page 32: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

5 OP. AVANZADAS DE STREAMING > STATEFUL

private def updateFuncAssociativeWithTime =

(iterator: Iterator[(DimensionValuesTime, Seq[AggregationsValues], Option[Measures])]) => {

iterator.filter {

case (DimensionValuesTime(_, _, Some(timeConfig)), _, _) =>

timeConfig.eventTime >= dateFromGranularity

case (DimensionValuesTime(_, _, None), _, _) =>

throw new IllegalArgumentException("Time configuration expected")

}.flatMap { case (dimensionsKey, values, state) =>

updateAssociativeFunction(values, state).map(result => (dimensionsKey, result))

}

}

Cube de SPARTA

Si filtramos en el Iterator estamos caducando información

Dentro de esta función realizamos el cálculo y actualizamos los estados de las keys

Page 33: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

REAL TIME AGGREGATION ENGINE: SPARK STREAMING + SPARK SQL

5.2 Optimizando Rendimiento

● MapPartitions

● MapValues y FlatMapValues

● CombineByKey

● Filter

● Partitioner

● Cache y Persist

5 OP. AVANZADAS DE STREAMING

Podéis ver todo esto aplicado en Cube de SPARTA!!

Page 34: Meetup Real Time Aggregations  Spark Streaming + Spark Sql

BIG DATACHILD`S PLAY

Gracias!!

Estrellas y Forks :) https://github.com/Stratio/Sparta

Contacto:[email protected]/in/gserranojc