Akka es un framework que trata de hacer la concurrencia y las aplicaciones distribuidas de una manera más sencilla. En este caso no veremos nada distribuido puesto que todo lo haremos en nuestra máquina local y nos centraremos en la concurrencia.
Habitualmente cuando programamos en ciertos lenguajes como por ejemplo en Java, generalmente trabajamos estos temas empleando el API que nos da acceso a crear threads o procesos y somos nosotros los que nos encargamos del paso de mensajes entre ellos, sus bloqueos, etc... Akka trata de aislarnos un poco de esto usando "actores".
Lo recomendable sería leernos los ejemplos y la documentación de Akka sobre actores pero intentaremos hacer un resumen corto.
Un actor es un proceso ligero que se ejecuta de manera concurrente a otros actores y que tiene una cola de mensajes, cumpliendo:
- El actor va leyendo los mensajes y procesándolos de uno en uno. De tal manera que si por ejemplo el actor se bloquea procesando un mensaje, aunque seguirá recibiendo mensajes que se encolarán, no procesará ninguno hasta que acabe de procesar el actual.
- Un actor puede crear otros actores, lo que al final acaba generando una jerarquía de actores (un actor es el padre de otros actores, etc)
- Un actor puede enviar mensajes a otros actores o a sí mismo. Estos mensajes son mensajes que definiremos nosotros de diferentes tipos, aunque existen también mensajes ya existentes en Akka por ejemplo para indicarle a un actor que muera.
Al final todos estos actores que se van creando pertenecen a un sistema de actores, que si le indicamos en algún momento que se cierre se encargará de ir matando todos los actores que existan.
Para nuestro ejemplo, (el código podéis encontrarlo aquí), hemos definido esta jerarquía de actores, que si bien probablemente pueda ser mejorable, nos puede servir de ejemplo para ver un poco cómo funciona todo:
Vamos a describir cada actor que se va a crear dentro de nuestro sistema de actores:
- QueueConsumer: es un actor único que se encarga de leer de una cola donde van entrando los tweets en tiempo real. Este actor cuando es arrancado crea los actores de cada equipo y simplemente cada vez que observa que hay algo en la cola, lo reenvía a los actores de cada equipo:
- TeamRecolector: cada uno de estos actores está encargado en primero instancia de crear los actores relacionados con cada jugador, el presidente, y el entrenador. Va quedándose aquellos tweets que le llegan que considera que están relacionados con el equipo, cuenta cuantos han llegado hasta el momento, los reenvía a sus hijos y cuando le llega el mensaje de guardar, le indica a sus hijos que la agregación en esa ventana ha acabado y guarda sus datos en ElasticSearch.
En realidad los PlayerRecolector, PresidentRecolector y CoachRecolector, heredan igual de TeamRecolector, de una clase Recolector en la que simplemente cada uno tiene que implementar lo que hace cuando se acaba el periodo de agregación (finishedPeriodAggregation), o procesar un tweet recibido:
La manera en que al final cada equipo está definido es un .conf dentro de la carpeta resources que es parseado cuando se crea el Actor:
Lo que hacemos es que cuando coincide que el Tweet contiene en su texto alguno de los términos relacionados (por ejemplo en el Actor que está agregando las apariciones de Colak, aparece un tweet que contenga colak, o cholak), sumamos uno en nuestra agregación puesto que el tweet cumple nuestro criterio.
Para minimizar los falsos positivos, si bien pueden producirse y probablemente la mejor aproximación sería hacer redes neuronales para detectar cuando se habla de un jugador, del club, o de futbol, el filtrado va como sigue:
- Solo se escuchan tweets relacionados con palabras clave de futbol como go, futbol, clasificación, etc...
- De esos tweets cada equipo filtra los que tienen términos relacionados con ello (su nombre, el nombre del estadio, etc)
- De los anteriores que ha filtrado el equipo, se le pasan a los actores hijos de cada equipo y ya ellos estiman si se está hablando de ese jugador, entrenador, etc...
Por lo que de acuerdo con lo anterior por ejemplo si alguien escribe un tweet del tipo: "En la Premiere de la nueva película de Leo DiCaprio en Barcelona", aunque no queremos acabaría clasificado, como tweet del barcelona y de Messi, puesto que Premiere es una palabra relacionada con el fútbol, Barcelona con el equipo y Leo es uno de los seudónimos de Messi...
Una vez dicho esto, si configuramos las claves del API de twitter de streaming y tenemos bien configurado nuestro ElasticSearch, cuando arranquemos, iremos viendo en los logs que estamos procesando tweets, y encontraremos también en ElasticSearch datos:
Una vez arrancado, arrancamos también Kibana y podemos ver en tiempo real, cómo va agregando y generando las gráficas que nosotros le hayamos indicado.
Primero configuramos correctamente el tiempo de actualización en la cabecera de Kibana:
Primero configuramos correctamente el tiempo de actualización en la cabecera de Kibana:
Una vez hecho esto si por ejemplo queremos ver el número de apariciones en cada ventana, actualizamos el filtro como sigue:
Y obtenemos por ejemplo gráficas de este tipo:
Si por ejemplo queremos ver de qué jugadores, o entrenadores están hablando más globalmente (en cada ventana), si por ejemplo queremos ver la gráfica de Messi podemos filtrar:
Y obtendríamos esta gráfica que es el número de tweets en cada ventana (30 segundos):
Obviamente tocando algo el modelo de datos y conociendo las opciones de Kibana, se puede jugar mucho más que con el esquema que hemos empleado que no deja de ser un ejemplo. De hecho no nos debería sorprender ver aparecer que apellidos comunes como "sanchez", "álvarez", etc, aparezcan con mucha frecuencia, simplemente por el hecho de como hemos comentado no ser capaces de catalogar bien cada tweet para un jugador.
Conclusiones
Si bien es cierto que obviamente vamos a tener bastantes falsos positivos y que probablemente no siempre que hablen de Messi aparezca una palabra relacionada con el Barcelona o el fútbol y por tanto nos estamos perdiendo muchos tweets de agregar, es un ejemplo de ver lo que puede hacer Akka sin despeinarse.
Pensemos que habiendo 20 equipos, con una media de 20 jugadores por equipo, se están montando 400 Actores además de los del entrenador, etc, y que están conviviendo repartiéndose las CPUs concurrentemente sin despeinarse.
Las medidas de sus pruebas en su web con un 8 cores, son realmente impresionantes soportando millares de actores y un montón de mensajes sin sobrecargar para nada la máquina.
Además gracias a las ventajas de Akka en el procesamiento distribuido, podríamos buscar maneras de segmentar los actores entre diferentes máquinas de manera que todo lo anterior funcionara de manera distribuida permitiendo muchísimas más opciones a la hora de mejorar el rendimiento o ingestar muchos más tweets.




















