Cómo optimizar el clúster de Spark con trabajos interactivos de Spark

En este artículo, aprenderás:
- Cómo reducir el tiempo de ejecución del trabajo de Spark
- ¿Qué es un trabajo interactivo en Ilum?
- Cómo ejecutar un trabajo interactivo de Spark
- Diferencias entre ejecutar un trabajo de Spark mediante la API de Ilum y la API de Spark
Tipos de trabajo de Ilum
Hay tres tipos de trabajos que puedes ejecutar en Ilum: Un solo trabajo , Trabajo interactivo y Código interactivo . En este artículo, nos centraremos en el Trabajo interactivo tipo. Sin embargo, es importante conocer las diferencias entre los tres tipos de trabajos, así que echemos un vistazo rápido a cada uno.
Con Trabajos individuales , puede enviar programas similares a código. Permiten enviar una aplicación de Spark al clúster, con código precompilado, sin interacción durante el tiempo de ejecución. En este modo, debe enviar un jar compilado a Ilum, que se utiliza para iniciar un solo trabajo. Puede enviarlo directamente o puede utilizar las credenciales de AWS para obtenerlo de un bucket de S3. Un ejemplo típico de uso de un solo trabajo sería algún tipo de tarea de preparación de datos.
Ilum también ofrece un interactivo Modo de código , que le permite enviar comandos en tiempo de ejecución. Esto es útil para tareas en las que necesita interactuar con los datos, como el análisis exploratorio de datos.
Trabajo interactivo
Los trabajos interactivos tienen sesiones de larga duración, en las que puede enviar datos de instancia de trabajo para que se ejecuten de inmediato. La característica principal de este modo es que no tiene que esperar a que se inicialice el contexto de Spark. Si los usuarios apuntaran al mismo identificador de trabajo, interactuarían con el mismo contexto de Spark. Ilum encapsula la lógica de la aplicación de Spark en un trabajo de Spark de larga duración que puede controlar las solicitudes de cálculo inmediatamente, sin necesidad de esperar a la inicialización del contexto de Spark.

Iniciar un trabajo interactivo
Echemos un vistazo a cómo se puede iniciar la sesión interactiva de Ilum. Lo primero que tenemos que hacer es montar Ilum. Puedes hacerlo fácilmente con el minikube. Un tutorial con la instalación de Ilum está disponible en este enlace . En el siguiente paso, tenemos que crear un archivo jar que contenga una implementación de la interfaz de trabajo de Ilum. Para usar la API de trabajo de Ilum, tenemos que agregarla al proyecto con algunos administradores de dependencias, como Maven o Gradle. En este ejemplo, usaremos un código de Scala con un Gradle para calcular PI.
El ejemplo completo está disponible en nuestro GitHub (en inglés) .
Si prefieres no construirlo tú mismo, puedes encontrar el archivo jar compilado aquí .
El primer paso es crear una carpeta para nuestro proyecto y cambiar el directorio a ella.
$ mkdir ejemplo-trabajo-interactivo
$ cd ejemplo-de-trabajo-interactivo
Si no tienes instalada la versión más reciente de Gradle en tu computadora, puedes consultar cómo hacerlo aquí . A continuación, ejecute el siguiente comando en un terminal desde el directorio del proyecto:
$ gradle init
Elija una aplicación Scala con Groovy como DSL. El resultado debería tener el siguiente aspecto:
Iniciar un demonio de Gradle (las compilaciones posteriores serán más rápidas)
Seleccione el tipo de proyecto a generar:
1: Básico
2: Aplicación
3: Biblioteca
4: Complemento de Gradle
Introducir selección (predeterminado: básico) [1..4] 2
Seleccione el idioma de implementación:
1: C++
2: Groovy
3: Java
4: Kotlin
5: Scala
6: Rápido
Introduzca la selección (por defecto: Java) [1..6] 5
¿Dividir la funcionalidad en varios subproyectos?:
1: no - solo un proyecto de aplicación
2: Sí - Proyectos de aplicaciones y bibliotecas
Introduzca la selección (por defecto: no - sólo un proyecto de aplicación) [1..2] 1
Seleccione el script de compilación DSL:
1: Groovy
2: Kotlin
Introducir selección (predeterminado: Groovy) [1..2] 1
¿Generar compilación con nuevas API y comportamiento (algunas características pueden cambiar en la próxima versión secundaria)? (predeterminado: no) [sí, no] no
Nombre del proyecto (por defecto: interactive-job-example):
Paquete fuente (predeterminado: interactive.job.example):
> Tarea :init
Obtén más ayuda con tu proyecto: https://docs.gradle.org/7.5.1/samples/sample_building_scala_applications_multi_project.html
CONSTRUIR EXITOSO en los años 30
2 tareas accionables: 2 ejecutadas
Ahora tenemos que agregar el repositorio de Ilum y las dependencias necesarias en su archivo build.gradle archivo. En este tutorial, usaremos Scala 2.12.
dependencias {
Implementación 'org.scala-lang:scala-library:2.12.16'
Implementación 'cloud.ilum:ilum-job-api:5.0.1'
compileOnly 'org.apache.spark:spark-sql_2.12:3.1.2'
}
Ahora podemos crear una clase Scala que extienda el trabajo de Ilum y que calcule PI:
paquete interactivo.job.example
importar cloud.ilum.job.Job
importar org.apache.spark.sql.SparkSession
importar scala.math.random
class InteractiveJobExample extends Job {
override def run(sparkSession: SparkSession, config: Map[String, Any]): Option[String] = {
val slices = config.getOrElse("slices", "2").toString.toInt
val n = math.min(100000L * segmentos, Int.MaxValue).toInt
val count = sparkSession.sparkContext.parallelize(1 until n, slices).map { i =>
val x = aleatorio * 2 - 1
val y = aleatorio * 2 - 1
si (x * x + y * y <= 1) 1 else 0
}.reducir(_ + _)
Algunos(s"Pi es aproximadamente ${4.0 * count / (n - 1)}")
}
}
Si Gradle ha generado algunas clases principales o de prueba, simplemente elimínalas del proyecto y haz una compilación.
$ construcción de gradle
El archivo jar generado debe estar en ' ./ejemplo-de-trabajo-interactivo/aplicación/compilación/libs/app.jar ', entonces podemos volver a Ilum. Una vez que todos los pods estén funcionando, por favor haga un reenvío de puerto para ilum-ui:
kubectl port-forward svc/ilum-ui 9777:9777
Abra la interfaz de usuario de Ilum en su navegador y cree un nuevo grupo:

Ponga un nombre a un grupo, elija o cree un clúster, cargue su archivo jar y aplique los cambios:

Ilum creará un pod de controlador de Spark y puede controlar el número de pods de ejecutor de Spark escalándolos. Una vez que el contenedor de Spark esté listo, vamos a ejecutar los trabajos:

Ahora tenemos que poner el nombre canónico de nuestra clase Scala
interactive.job.example.InteractiveJobExample
y defina el parámetro slices en formato JSON:
{
"config": {
"rebanadas": "10"
}
}
Debería ver el resultado justo después de que se iniciara el trabajo

Puede cambiar los parámetros y volver a ejecutar un trabajo y sus cálculos se realizarán en el acto.
Comparación interactiva y de un solo trabajo
En Ilum también se puede ejecutar un solo trabajo. La diferencia más importante en comparación con el modo interactivo es que no tiene que implementar la API de trabajo. Podemos usar el jar SparkPi de los ejemplos de Spark:

Ejecutar un trabajo como este también es rápido, pero los trabajos interactivos sí lo son. 20 veces más rápido (4 s frente a 200 ms) . Si desea iniciar un trabajo similar con otros parámetros, tendrá que preparar un nuevo trabajo y volver a cargar el jar.
Comparación de Ilum y Apache Spark simple
He configurado Apache Spark localmente con un Bitnami/Chispa Imagen de Docker. Si también quieres ejecutar Spark en tu máquina, puedes usar docker-compose:
$ curl -LO https://raw.githubusercontent.com/bitnami/containers/main/bitnami/spark/docker-compose.yml
$ docker-compose up
Una vez que Spark se esté ejecutando, debería poder ir a localhost:8080 y ver la interfaz de usuario de administración. Necesitamos obtener la URL de Spark del navegador:
A continuación, tenemos que abrir el contenedor de Spark en modo interactivo usando
$ docker exec -it <containerid> -- bash
Y ahora dentro del contenedor, podemos enviar el trabajo de sparkPi. En este caso, usaremos SparkiPi del jar de ejemplos y, como parámetro maestro, pondremos la URL del navegador:
$ ./bin/spark-submit --class org.apache.spark.examples.SparkPi\
--maestro spark://78c84485d233:7077 \
/opt/bitnami/chispa/ejemplos/frascos/spark-examples_2.12-3.3.0.jar\
10
Resumen
Como puede ver en el ejemplo anterior, puede evitar la complicada configuración e instalación de su cliente Spark mediante el uso de Ilum. Ilum se hace cargo del trabajo y le proporciona una interfaz sencilla y cómoda. Además, le permite superar las limitaciones de Apache Spark, que puede tardar mucho tiempo en inicializarse. Si tiene que realizar muchas ejecuciones de trabajos con una lógica similar pero con parámetros diferentes y desea que los cálculos se realicen de inmediato, definitivamente debe usar el modo de trabajo interactivo.

Similitudes con Apache Livy
Ilum es una herramienta nativa de la nube para administrar implementaciones de Apache Spark en Kubernetes. Es similar a Apache Livy en términos de funcionalidad: puede controlar una sesión de Spark a través de la API REST y crear una interacción en tiempo real con un clúster de Spark. Sin embargo, Ilum está diseñado específicamente para entornos modernos y nativos de la nube.
Usamos Apache Livy en el pasado, pero hemos llegado a un punto en el que Livy simplemente no era adecuado para entornos modernos. Tito Livio es obsoleto en comparación con Ilum. En 2018, comenzamos a trasladar todos nuestros entornos a Kubernetes y tuvimos que encontrar una manera de implementar, monitorear y mantener Apache Spark en Kubernetes. Esta fue la ocasión perfecta para construir Ilum.