Análisis de tendencias (geolocalizadas) en Twitter
Tabla de Contenidos
- Novedades
- Descripción del proyecto
- Descripción de arquitecturas software
- Descripción de los microservicios a desarrollar
- Bibliotecas de Python para la API de Twitter
- Descripción del despliegue
- Automatización de tareas en la nube
- Orquestación de máquinas virtuales
- Enlaces de Interés
- Licencia
Novedades
- Pincha aquí para acceder a los avances realizados en el hito 5. En dicho documento explico el proceso seguido para la conexión entre máquinas y como creo la BD e inserto.
- Pincha aquí para ver la orquestación de máquinas virtuales.
- Pincha aquí para ver las comprobaciones realizadas en el hito 5.
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 en capas: arquitectura cliente-servidor, tiene 3 o más capas, normalmente se suelen incluir la capa de presentación, la de aplicación, la de lógica de negocio y la de acceso a datos. El problema principal es que solo permite escalado dentro de cada una de las capas, siendo al final alguna de ellas un cuello de botella.
- Arquitectura dirigida por eventos: tiene una cola de eventos que se originan en el usuario, pero también de una parte a otra de la arquitectura. Es difícil de testear y su desarrollo es más complicado que la anterior.
- Arquitectura microkernel: arquitectura casi monolítica, con un núcleo central al que se pueden añadir funcionalidades mediante plugins, siendo su problema principal la escalabilidad, ya que el núcleo puede representar un cuello de botella.
- Arquitectura basada en microservicios: arquitectura muy popular, se caracteriza por usar unidades que se van a desplegar de forma independiente y por poder usar tecnologías subyacentes que van desde la virtualización completa en la nube hasta el uso de contenedores Docker en una sola máquina virtual.
- Arquitectura basada en espacios: arquitectura antigua, de la década de los 90.
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:
- 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.
- 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])
. - 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.
- Mostrar información: en este microservicio solo nos interesa mostrar la información relevante de alguna manera específica.
- 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]:
- Tweets: búsqueda, publicación, filtrado, etc.
- Anuncios: gestión de campañas, análisis, etc.
- Contenido multimedia: subir y acceder a fotos, vídeos, GIF animados, etc.
- Tendencias: trending topics.
- Geo: información sobre lugares conocidos, lugares cerca de una ubicación, etc.
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:
- Testear ejecución de Flask lanzada.
- 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
- Testear que se ha desplegado incorrectamente.
- Testear que se visualizan todos los elementos.
- 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
- Testear que se crea un elemento.
- Testear que se modifica un elemento.
- 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
/
y/status
: devuelve el JSON {“status”:”OK”}error en la ruta
: devuelve el JSON {“msg error”:”URL not found”}/data_twitter
: lista todos los elementos del JSON/data_twitter/Rudy
: lista todos los elementos del JSON/data_twitter
con PUT: crea un nuevo usuario del JSONcurl -i -X PUT https://glacial-castle-84194.herokuapp.com/data_twitter # para comprobar que se ha creado curl -i https://glacial-castle-84194.herokuapp.com/data_twitter/newID
/data_twitter
con POST: modifica un nuevo usuario del JSONcurl -X POST https://glacial-castle-84194.herokuapp.com/data_twitter/Rudy
/data_twitter
con DELETE: elimina un usuario del JSONcurl -X DELETE https://glacial-castle-84194.herokuapp.com/data_twitter/Rudy
-
/BD
con GET: muestra en HTML la base de datos. /add_bd
con POST: inserta en la base de datos.
Descripción de los ficheros usados
-
main.py
: fichero que implementa la clase API REST haciendo uso del microframework Flask -
test/main_test.py
: fichero que testea la clase del main.py -
data/twitterAPI.py
: fichero que se conecta a la API de Twitter y extrae información data/data_json
: fichero que contiene la estructura de datos- name: nombre de la tendencia
- url: link del enlace de la tendencia
- query: nombre de la consultas
- tweet_volume: volumen de tweets dedicados a esa tendencia
-
scripts/
: carpeta que contiene los scripts usados para la creación del usuario, la base de datos y la tabla. html/
: carpeta que contiene las plantillas y los diseños para la visualización de las rutas ‘/BD’ y ‘/add_bd’.
Pasos para hacer el despliegue (Github+Travis+Heroku)
-
Identificarse en Travis mediante Github.
-
Añadir un archivo .travis.yml al repositorio para decirle a Travis CI qué hacer, el cual contiene:
- El lenguaje del programación y la versión usada. En este caso he hecho uso de Python 3.6.7 para OSX.
- El comando para instalar las dependencias, el cual contiene las dependencias a instalar.
-
El comando para ejecutar los tests.
language: python python: - "3.6.7" install: - pip install -r requirements.txt script: - python3 test/main_test.py
- 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.
-
Crear cuenta en Heroku.
-
Instalar el comando de Heroku Command Line Interface (CLI). Como anotación comentar que cada semana actualizan la versión.
-
Identificarse introduciendo nuestras credenciales de la cuenta de Heroku:
heroku login
-
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
- 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
- Crear el fichero runtime.txt, en mi caso la versión de Python 3.7.0.
python-3.7.0
-
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. -
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.
-
git push heroku master
: solo para Heroku. -
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:
- ansible.cfg: fichero de configuración básica, que básicamente le dice a Ansible que tiene que mirar en el fichero ansible_hosts.
- ansible_hosts: fichero para definir una serie de requerimentos (nombre de la máquina, puerto SSH para acceder a la máquina virtua, host).
- ansible_playbook.yml: fichero para definir las intrucciones a ejecutar (python, git, pip, flask, clonar repositorio).
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
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.
-
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).
-
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.
-
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).
-
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.
-
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
- Clonar mi repositorio.
- Acceder a la carpeta orquestación (
cd orquestacion/
) y ejecutarvagrant up --no-parallel —provider=azure
. - 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
-
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
). -
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).
-
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
-
Comprobación de @jmv74211 al aprovisionamiento de @gecofer disponible en este enlace.
-
Comprobación de @gecofer al aprovisionamiento de @jmv74211 disponible en este enlace.
-
Comprobación de @luiisgallego al aprovisionamiento de @gecofer disponible en este enlace.
-
Comprobación de @gecofer al aprovisionamiento de @luiisgallego disponible en este enlace.
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.