Análisis de tendencias (geolocalizadas) en Twitter

Tabla de Contenidos

Novedades

Descripción del proyecto

Twitter junto con Instagram son dos de las plataformas sociales más usadas actualmente, por eso mismo, miles de usuarios comparten todo tipo de información en ellas. Este tipo de comportamientos benefician a las empresas dándoles potestad en la obtención de información muy valiosa, cómo por ejemplo ver qué tendencias o trending topics son los más comentados o qué ciudades son las más comentadas en la red. En este caso, yo me voy a centrar en la obtención de datos geolocalizados, es decir, en la extracción de trending topics o tendencias de los usuarios en Twitter para una región determinada. Para así, poder clasificar las tendencias y establecer la tendencia mayoritaria para una region determinada.

Descripción de arquitecturas software

Actualmente, las arquitecturas software modernas buscan la consistencia en la velocidad de respuesta al usuario. Sin embargo, en el mercado existen muchos tipos de arquitecturas, es por ello que a veces se hace difícil concretar qué arquitectura se va a utilizar [2]:

Arquitectura seleccionada

Entonces, resulta bastante claro que de todas las arquitecturas comentadas anteriormente vayamos a hacer uso de la arquitectura basada en microservicios, ya que es la que más actual y la que menos problemas presenta, además de que nos permite tener diferentes servicios trabajando de forma totalmente independiente unos de otros.

Descripción de los microservicios a desarrollar

Para realizar la arquitectura se va a hacer uso del lenguaje Python, y para el desarrollo de los microservicios se puede usar cualquier microframework web para Python, en este caso existe la posibilidad de usar Django (más complejo o pensado para un proyecto de grandes dimensiones o que crezca) o Flask (más sencillo). Es por ello, que tras haber buscado documentación, hablado con usuarios de ambos microframework y ser la primera vez que uso este tipo de tecnología, me he decantado por Flask. Los microservicios previstos a desarrollar son los siguientes:

  1. Consultar API de Twitter: en este microservicio solo nos vamos a centrar en acceder, consultar y bajarnos información de la API, información obtenida en un JSON.
  2. Procesar información: en este microservicio vamos a quedarnos con los datos referentes a las tendencias según su localización, en un JSON: API.trends_place(id[, exclude]).
  3. Almacenar información: en este microservicio nos vamos a centrar en crear una estructura para los datos que hemos realizado, usando principalmente una BD como MongoDB.
  4. Mostrar información: en este microservicio solo nos interesa mostrar la información relevante de alguna manera específica.
  5. Además, necesitamos un sistema de centralización de logs, al cual todos deben comunicarse.

Comunicación entre los microservicios

La comunicación entre servicios será realizada por brokers, en concreto con RabbitMQ, que es un sistema de manejo de colas.

Bibliotecas de Python para la API de Twitter

Actualmente, la API de Twitter nos permite acceder a todo tipo de información de forma más simple que la de Instagram, es por eso que me he decantado por esta red social. A continuación, se muestran algunos datos a los que podemos acceder [1]:

Python cuenta muchas bibliotecas desarrolladas para la API de Twitter. Sin embargo, al no haber usado nunca ninguna me es dífil elegir que biblioteca es la mejor. Es por ello, que voy hacer uso de tweepy ya que he oído hablar de ella bastante bien y tiene bastante documetación en la web. De todas maneras, existen otras librerías cómo twython, python-twitter o TwitterAPI.

Descipción de los tests en Python (código sin test código roto)

Para testear en Python [3], puedo usar algunas de las librerías que me permiten implementar pruebas unitarias en dicho lenguaje como unittest, doctest o pytest [4]. En este caso yo voy hacer uso de la biblioteca unittest, ya que nos ofrece toda la potencia del lenguaje para probar nuestros programas, lo que significa que ayuda a determinar rápidamente el impacto de cualquier modificación en el resto del código.

Para realizar la configuración de los test correctamente, voy hacer uso de Travis CL, que es un sistema distribuido de generación e integración continua libre, que me permite conectar mi repositorio de Github y testear después de cada push que haga [5] [6]. En el apartado siguiente, explico como establecer el testeo con travis, cuando quiero desplegar.

Por tanto, para establecer un testeo cada vez que haga git push, he seguido el tutorial de Travis.

Para testear el archivo main.py, me he creado un archivo main_test.py, en el cual me he creado 8 funciones que comprueban el código, haciéndolo robusto:

  1. Testear ejecución de Flask lanzada.
  2. Testear que se ha desplegado correctamente.
      # Testear que se ha desplegado correctamente
      def test1_index(self):
     # result = requests.get('http://127.0.0.1:5000/')
     result = self.app.get("/")
     self.assertEqual(result.status_code, 200)
     self.assertEqual(result.content_type, "application/json")
    
     pass
    
  3. Testear que se ha desplegado incorrectamente.
  4. Testear que se visualizan todos los elementos.
  5. Testear que se visualiza uno de los elementos.
      # Testear que se visualiza uno de los elementos
      def test4_get_data(self):
     result = self.app.get("/data_twitter/Rudy")
     self.assertEqual(result.status_code, 200)
     self.assertEqual(result.content_type, "application/json")
     self.assertTrue(result.get_json(), "The list is empty")
    
     # Escribimos la ruta mal
     result_bad = self.app.get("/hola")
     self.assertEqual(result_bad.status_code, 404)
    
     pass
    
  6. Testear que se crea un elemento.
  7. Testear que se modifica un elemento.
  8. Testear que se elimina un elemento.
      # Testear que se elimina un elemento
      def test7_delete_data(self):
     result_delete = self.app.delete("/data_twitter/hola")
     self.assertEqual(result_delete.status_code, 200)
     self.assertEqual(result_delete.content_type, "application/json")
     self.assertTrue(result_delete.get_json(), "The list is empty")
    
     result_post1 = self.app.post("/data_twitter/#GHVIPGala12")
     result_delete1 = self.app.delete("/delete_data/#GHVIPGala12")
     result_post2 = self.app.post("/data_twitter/#GHVIPGala12")
     self.assertEqual(result_post2.status_code, 404)
    
     pass
    

Descripción del despliegue

Despliegue en PaaS

Cuando se quiere desplegar una aplicación sobre una infraestructura ya definida y que no va a cambiar se necesita un Platform as a Service o PaaS. Entre los posibles servicios que hay Heroku o OpenShift, vamos a escoger Heroku, ya que es un servicio fiable, gratuito, ofrece muchas opciones a la hora de elegir el lenguaje y permite integrar Github con Travis.

Despliegue: https://glacial-castle-84194.herokuapp.com

Rutas utilizadas en la aplicación

Descripción de los ficheros usados

Pasos para hacer el despliegue (Github+Travis+Heroku)

  1. Identificarse en Travis mediante Github.

  2. Añadir un archivo .travis.yml al repositorio para decirle a Travis CI qué hacer, el cual contiene:

  1. Habilitar el repositorio en Travis, para así cada vez que se haga git push se compilen en Travis. Para ello, una vez iniciado sesión en Travis mediante Github, tengo que seleccionar la pestaña del repositorio que quiero ejecutar.

  1. Crear cuenta en Heroku.

  2. Instalar el comando de Heroku Command Line Interface (CLI). Como anotación comentar que cada semana actualizan la versión.

  3. Identificarse introduciendo nuestras credenciales de la cuenta de Heroku: heroku login

  4. Para que Heroku pueda encontrar el archivo principal del proyecto, debemos definirnos un archivo Procfile en Heroku [7], el cual especifica los comandos que son ejecutados por la aplicación al inicio, que contendrá la siguiente instrucción web: gunicorn main:app, usaremos gunicorn ya que nos permite administrar las peticiones simultaneas que nuestra aplicación reciba. El archivo debe estar en el directorio raíz de tu app.

  web: gunicorn main:app
  1. Creo el fichero requirements.txt, para instalar las dependencias. Este fichero se puede instalar de diversas formas, no es recomendable usar pip freeze > requirements.txt, ya que te mete basura [8]. Debemos recordar añadir gunicorn. Para ello hacer uso de pyenv.
  Flask==1.0.2
  requests==2.20.1
  gunicorn==19.9.0
  1. Crear el fichero runtime.txt, en mi caso la versión de Python 3.7.0.
  python-3.7.0
  1. Crear una aplicación en Heroku, este proceso se puede hacer de dos maneras: por terminal heroku create o mediante la web Create new App.

  2. Configuar el despliegue automático asociando la aplicación de Heroku con nuestra cuenta de GitHub.

    • En web, accedemos a la aplicacion creada y buscamos Deploy
    • Seleccionamos GitHub como Deployment method
    • Conectamos la app en introduciendo nuestra datos de GitHub
    • Indicamos el repositorio de GitHub de nuestra aplicación
    • Activamos los despliegues automáticos y que Travis ejecute antes de desplegar.

  1. git push heroku master: solo para Heroku.

  2. git push: para Github+Travis+Heroku.

Despliegue de la infraestructura en máquina virtual local

Para el despliegue de la aplicación en una máquina virtual local, se ha hecho uso de Ansible junto con Vagrant. Previamente a la realización de un clone a mi repositorio, se debe instalar Ansible, Vagrant y VirtualBox, herramientas necesarias para ejecutar la aplicación. Una vez realizados estos procesos, debemos dirigirnos al directorio provision > vagrant_ubuntu y ejecutar la sentencia vagrant up, la cual creará una máquina virtual en VirtualBox y ejecutará el playbook con lo indispensable para el despliegue.

Vagrant

Se ha utilizado la herramienta Vagrant para generar entornos de desarrollo reproducibles y compartibles de forma muy sencilla, ya que crea y configura máquinas virtuales a partir de simples ficheros de configuración. El fichero donde se describe la infraestructura se llama Vagrantfile y es utilizado para el despliegue (enlace).

Pincha aquí, para saber más información sobre el despliegue en máquina virtual local con Vagrant.

Ansible

Para el provisionamiento se ha hecho uso de Ansible (versión 2.7.2) Como software para automatizar el proceso de aprovisionamiento se ha utilizado Ansible, creando previamente los siguientes ficheros:

Pincha aquí, para saber más información sobre la gestión de configuraciones con Ansible.

Si no se utiliza Vagrant, también se puede realizar el provisionamiento utilizando órdenes de ansible, es decir, haciendo uso de la orden ansible-playbook ansible_playbook.yml.

Despliegue de la infraestructura en Azure

Se ha creado una máquina virtual en Azure con Ubuntu 14.04 LTS, la misma usada para el despliegue en la máquina virtua local. Para lanzar la aplicación, debemos conectar a la mv ssh gemaAzure@23.97.225.1 y ejecutar el provisionamiento que con todos los módulos necesarios se uso de ansible-playbook -i ansible_hosts -b ansible_playbook.yml.

Lanzamos nuestra aplicación con gunicorn y efectivamente comprobamos que podemos aceder:

La dirección IP: 23.97.225.1

MV: http://23.97.225.1

Pincha aquí, para saber más información sobre el despliegue en Azure.

Automatización de tareas en la nube

El objetivo de las plataformas de virtualización es, eventualmente, crear y gestionar una máquina virtual que funcione de forma aislada del resto del sistema y que permita trabajar con sistemas virtualizados de forma flexible, escalable y adaptada a cualquier objetivo. Para ello, usaremos los clientes de línea de órdenes de los servicios en la nube para crear instancias de máquinas virtuales y otros recursos necesarios para las mismas. Estas instancias, posteriormente, se provisionarán y se instalará en ella la aplicación que se ha venido usando hasta ahora.

  1. En este caso vamos hacer uso de la CLI de Azure, para ello primero deberemos instalarla, y una vez instalada iniciar sesión y autenticarse en el mismo, además de unos pequeños comandos para ver el listado de imágenes de máquinas virtuales disponibles (pincha aquí para ver la documentación).

  2. Una vez que podemos crear máquinas virtuales desde la línea de comandos, vamos a razonar la justificación de la elección de la imagen del sistema operativo (pincha aquí para ver dicha justificación). En nuestro caso, hemos seleccionado el sistema Ubuntu Server 18.04 LTS.

  3. Una vez escogido el sistema operativo, pasamos a la elección del tamaño de la imagen para dicha máquina virtual (pincha aquí para ver dicha justificación).

  4. Una vez escogido el sistema operativo, se va a justificar la elección del centro de datos en el cual se creará la máquina virtual (pincha aquí para ver dicha justificación). En este caso, se ha hecho uso del centro de datos del centro de Francia.

  5. Por último, ya solo nos hace falta crear el script de aprovisionamiento, para eso pincha aquí para ver el código, aquí para ver la documentación del mismo y aquí para ver su salida.

MV2: 40.89.158.208

Orquestación de máquinas virtuales

Se usa Vagrant para provisionar una o preferiblemente varias máquinas virtuales usando un proveedor de servicios cloud, en este caso se ha usado Azure. En el directorio orquestacion se encuentran los archivos necesarios para llevar a cabo la creación y provisión de las máquinas virtuales y la documentación se encuentra aquí. La documentación donde se explica el proceso para la creación y uso de la base de datos, se puede encontrar aquí.

Despliegue Vagrant: 20.188.32.253

Pasos para probarlo

  1. Clonar mi repositorio.
  2. Acceder a la carpeta orquestación (cd orquestacion/) y ejecutar vagrant up --no-parallel —provider=azure.
  3. Cuando se terminen de crear y provisiona ambas máquinas, abrir las dos con SSH:
  # Para la máquina principal
  $ ssh vagrant@mvprincipalcc.francecentral.cloudapp.azure.com

  # Para la máquina con la base de datos
  $ ssh vagrant@mvbasedatoscc.francecentral.cloudapp.azure.com
  1. Dentro de la máquina principal, se accede a la carpeta proyecto (cd proyecto/) y se lanza la aplicación en el puerto 80 con (sudo gunicorn -b :80 main:app).

  2. Accedemos al navegador con la IP pública de la máquina principal (http://ip_publica_maquina_principal:80/status) y obtenemos el status ok (mirar IP en Azure).

  3. Accedemos al navegador con la IP pública de la máquina principal (http://ip_publica_maquina_principal:80/BD) y visualizamos la interfaz web, la cual esta conectada con la base de datos.

Comprobaciones del hito 5

Enlaces de Interés

Licencia

Proyecto bajo licencia GNU GLP V3.

Nota: Se debe tener en cuenta que la realización de un proceso de desarrollo conlleva modificaciones en el futuro, pudiendo modificar la documentación o añadiendo nuevas funcionalidades.