2. Apache Storm
● Storm tiene dos modos de operación local mode y remote mode (cluster).
● El entorno de desarrollo de storm tiene todo lo necesario para desarrollar y
probar topologías storm en modo local.
● Un storm cluster es gestionado por un nodo maestro llamado Nimbus.
● La máquina de desarrollo se comunica con Nimbus y le envía el código
empaquetado en jar y las topologías para ejecutar en el cluster. Nimbus se
encarga de distribuir el código en el cluster y asignar los workers para ejecutar
la topología.
● Para comunicar el entorno de desarrollo con el cluster se utiliza el comando
storm.
3. Apache Storm en modo local
1. Descargar una release
1. Descomprimir
1. Añadir el directorio bin/ al PATH
1. Confirmar que bin/storm es ejecutable
1. Crear el fichero de configuración local de Storm
~/.storm/storm.yaml
1. Establecer la IP del servidor nimbus.
nimbus.host: localhost
4. Apache Storm en modo local
7. Iniciar el Zookeeper
zkServer.sh start
8. Iniciar el Nimbus
storm nimbus
9. Iniciar el Supervisor
storm supervisor
5. Ejecución de topologías
● Storm tiene dos modos de ejecución: local mode y distributed mode.
○ En local mode ejecuta todos los procesos simulando los nodos workers
con threads. El local mode es muy útil para probar y desarrollar
topologías.
○ En distributed mode, Storm se ejecuta en un cluster de máquinas.
Cuando se envía la topología al nodo maestro se adjunta todo el código
necesario para su ejecución. El nodo maestro se ocupa de distribuir el
código y reservar los workers para ejecutar la topología. Si algún worker
se cae el maestro los re-asigna.
6. Configuración de topologías
Config conf = new Config();
conf.setDebug(true);
conf.setNumWorkers(2);
TOPOLOGY_WORKERS: Indica cuantos procesos se quieren reservar en el
cluster para ejecutar la topología. Cada componte en la topología ejecutará
una serie de hilos. El número de hilos de un componente determinado se
establece en los métodos setBolt y setSpout.
Por ejemplo podemos tener 300 hilos a lo largo de todos los componentes y
50 procesos worker. Por tanto, cada proceso worker ejecutará 6 hilos, cada
uno de los cuales puede pertenecer a un componente distinto.
TOPOLOGY_DEBUG: Cuando se encuentra a true genera un log por cada
mensaje emitido por un componente.
7. Stream groupings
● Un stream groping indica a la topología como se deben enviar las tuplas
entre dos componentes. Define como el stream se debe particionar entre los
bolts.
1.ShuffleGrouping: envía la tupla a una tarea aleatoria. Tiene el efecto de
distribuir de forma proporcional el procesado de las tuplas. Útil para
operaciones atómicas como operaciones matemáticas.
2.FieldsGrouping: agrupa un stream por un subconjunto de campos. Esto
implica que valores similares vayan a las mismas tareas. FieldsGrouping
está implementado utilizando mod hashing
3. All grouping: El stream se copia en todas las tareas bolt. Hay que
utilizarlo con precaución. Es útil para enviar señales a todos los bolts.
8. Stream groupings
4. Global grouping: El stream entero va a un solo bolt, en concreto a la tarea
bolt con el ID más bajo.
5. None grouping: Indica que no es relevante el orden, es equivalente a
shuffle grouping.
6. Direct grouping: Un agrupamiento especial. El productor de la tupla
decide que tarea va a consumir la tupla. Direct grouping solo se puede
utilizar en streams declarados como direct streams. Las tuplas emitidas a un
direct stream se deben generar con los métodos emitDirect. Un bolt puede
obtener los ids de los consumidores por medio de TopologyContext.
7. Local grouping: Si el bolt tiene 1 o más tareas en el mismo proceso
worker, las tuplas se mandan a estas tareas intra-proceso.
9. Linea de comandos: storm
Los parámetros del comando storm son:
1.jar
2.kill
3.activate
4.deactivate
5.rebalance
6.repl
7.classpath
8.localconfvalue
9.remoteconfvalue
10.nimbus
11.supervisor
12.ui
13.drpc
10. storm jar
● Ejecuta el método main de la clase class con los argumentos especificados.
Se configuran en el classpath los jars de ~/.storm y la configuración.
● El proceso StormSubmitter sube el jar indicado a la hora de enviar la
topología.
storm jar topology-jar-classpath class ...
11. storm kill
● Termina la topología con el nombre topology-name. Storm primero finaliza
los spouts de la topología y los mensajes que están pendientes de procesar
se procesan.
● A continuación para los workers y limpia su estado. Se puede configurar el
tiempo de desactivación y espera con el flag -w.
storm kill topology-name [-w wait-time-secs]
12. storm activate/deactivate
● Activa los spouts de la topología especificada.
storm activate topology-name
● Desactiva los spouts de la topología especificada.
storm deactivate topology-name
13. storm rebalance
● Permite hacer un re-balanceo de la topología cuando se añaden nuevos
nodos al cluster.
● Rebalance primero desactiva la topología en ejecución y después
redistribuye los workers en la nueva configuración del cluster. La topología
se inicia desde su estado previo.
storm rebalance topology-name [-w wait-secs]
14. storm
● Lanza el demonio supervisor.
storm supervisor
● Lanza el demonio UI. El UI proporciona un interfaz web para storm y
muestra información sobre las topologías en ejecución.
storm ui
● Lanza el demonio Distributed RPC.
storm drpc
15. Arrancando y parando topologías
en un cluster remoto
● Cuando se desea enviar una topología a un cluster remoto hay que cambiar la
llamada LocalCluster a StormSubmitter e implementar el método submitTopology
que es responsable de enviar la topología al cluster.
● Es necesario establecer la dirección IP del host maestro en ~/.storm/storm.yaml
nimbus.host: "123.45.678.890"
16. Paralelismo de Topologías
● Storm distingue entre las siguientes 3 entidades:
1. Procesos Worker
2. Executors (threads)
3. Tasks
17. Paralelismo de Topologías
● Un proceso worker ejecuta un subconjunto de la topología. Un proceso
worker pertenece a una topología determinada y puede ejecutar 1 o más
executors para 1 o más componentes (Spouts o Bolts) de la topología. Una
topología en ejecución consiste en muchos procesos ejecutándose en
muchas máquinas de un cluster Storm.
● Un executor es un hilo que es creado por un proceso worker. Puede
ejecutar 1 o más tareas para el mismo componente (spout o bolt).
18. Paralelismo de Topologías
● Una task lleva a cabo el procesado de datos. Cada Spout o Bolt
implementado en el código ejecuta todas las tareas necesarias en el cluster.
● El número de tareas de un componente es siempre el mismo a lo largo del
ciclo de vida de la topología, pero el número de executors (threads) para un
componente puede cambiar a lo largo del tiempo.
● La siguiente condición siempre se cumple:
#threads <= #tasks.
● Por defecto el número de tasks es el mismo que el número de executors. Es
decir Storm ejecuta una tarea por hilo.
19. Paralelismo de Topologías
● Storm tiene el siguiente orden de preferencia en configuración:
defaults.yaml
< storm.yaml
< topology-specific configuration
< internal component-specific configuration
< external component-specific configuration
● Número de procesos worker
Cuantos procesos se crean para la topología a lo largo de las máquinas
del cluster.
Opción de configuración: TOPOLOGY_WORKERS
En código: Config#setNumWorkers
20. Paralelismo de Topologías
● Número de executors (threads)
○ Cuantos executors se pueden crear por componente.
■ En código: TopologyBuilder#setSpout()
TopologyBuilder#SetBolt()
A partir de storm v0.8 se puede especificar con parallelism_hint el
número de executors para un bolt concreto.
● Número de tareas (tasks)
○ Indica cuantas tareas se pueden crear por componente.
Configuración: TOPOLOGY_TASKS
Código: ComponentConfigurationDeclarer#setNumTasks()
topologyBuilder.setBolt("green-bolt", new GreenBolt(), 2)
.setNumTasks(4)
.shuffleGrouping("blue-spout);
22. Cambiando el paralelismo en ejecución
En Storm es posible modificar el paralelismo de una topología en
ejecución.Lo cual se conoce como rebalancing,
Hay dos opciones para el rebalance:
1. Utilizar el web UI de storm.
2. Utilizar la línea de comandos.
storm rebalance mytopology -n 5 -e blue-spout=3 -e
yellow-bolt=10
23. Paralelizando spouts
● Se puede paralelizar la entrada a los spouts utilizando la clase
TopologyContext y dividiendo el stream de entrada entre las instancias
disponibles.
public void open(Map conf, TopologyContext context,
SpoutOutputCollector collector) {
//Obtenemos el num de spouts del contexto
int spoutsSize =
context.getComponentTasks(context.getThisComponentId(
)).size();
//Obtenemos el ID de este spout
int myIdx = context.getThisTaskIndex();
String[] tracks = ((String)
conf.get("track")).split(",");
StringBuffer tracksBuffer = new StringBuffer();
for(int i=0; i< tracks.length;i++){
//Comprobamos si este spout debe procesar el stream
If( i % spoutsSize == myIdx){
tracksBuffer.append(",");
tracksBuffer.append(tracks[i]);
}