scieee AI-readable full text Open interactive document viewer

Procesamiento en tiempo real de log de actividad en sistemas de Receta Electrónica y uso de técnicas avanzadas de clustering en entornos Hadoop

Cores Costa, Daniel

Abstract

El objetivo de este proyecto es proporcionar una herramienta capaz de analizar los logs de actividad de un sistema de Receta Electrónica en tiempo real, en concreto, del sistema de Dispensación Electrónica implantado en el SERGAS, de tal forma que los usuarios puedan tener a su disposición una serie de informes que pueden actualizar utilizando los parámetros que deseen. Se busca una solución que ofrezca un sistema robusto y con unos tiempos de respuesta reducidos con el fin de poder ofrecer un servicio en tiempo real y de alta disponibilidad prestando especial atención a la posibilidad de que se produzca pérdida de datos. En este sentido, las etapas de análisis tecnológico y de diseño de la arquitectura del sistema cobrarán especial relevancia a la hora de poder confeccionar un sistema de estas características. Surgen un gran número de cuestiones inherentes al procesamiento en tiempo real que se deben solventar y que en el proyecto anterior no se tenían en cuenta. Por un lado, necesitamos establecer un mecanismo de comunicación robusto con el sistema de Receta Electrónica que no sea sensible al estado del sistema o de la red. Por otro lado, se imponen unas fuertes restricciones sobre los tiempos de procesamiento, en este sentido, cabe destacar que cuando nos referimos a procesamiento en “tiempo real”, realmente, nos estamos refiriendo a sistemas de procesamiento NRT (“near real time”), se trata de sistemas capaces de procesar y analizar los datos a medida que son recibidos ofreciendo unos tiempos de respuesta muy bajos pero que, realmente, tienen un pequeño retardo con respecto a los datos originales.

Full text

Memoria Trabajo Fin de Grado Procesamiento en tiempo real de log de actividad en sistemas de Receta Electrónica y uso de técnicas avanzadas de clustering en entornos Hadoop Autor: Daniel Cores Costa Tutores: Tomás Fernández Pena Adolfo Sanz Anchelergues Septiembre 2015 HP – Universidad Santiago de Compostela D. Tom´as Fern´andez Pena, Profesor do Departamento de Electr´onica e Computaci´on da Universidade de Santiago de Compostela, e D. Adolfo Sanz Anchelergues, Consultor Senior Business Intelligence de Hewlett Packard Customer Delivery Services, INFORMAN: Que a presente memoria, titulada Procesamiento en tiempo real de log de actividad en sistemas de Receta Electr´onica y uso de t´ecnicas avanzadas de clustering en entornos Hadoop, presentada por D. Daniel Cores Costa para superar os cr´editos correspondentes ao Traballo de Fin de Grao da titulaci´on de Grao en Enxe˜nar´ıa Inform´atica, realizouse baixo nosa direcci´on no Departamento de Electr´onica e Computaci´on da Universidade de Santiago de Compostela. E para que as´ı conste aos efectos oportunos, expiden o presente informe en Santiago de Compostela, a 03/09/2015: O director, O codirector, O alumno, (Tom´as Fern´andez Pena) (Adolfo Sanz Anchelergues) (Daniel Cores Costa) i Introducción Página 2 de 123 Contenido 1. INTRODUCCIÓN ......................................................................................................................... 5 1.1. CONTEXTO .................................................................................................................................. 5 1.1.1. HP ...................................................................................................................................... 5 1.1.2. Análisis de log de actividad en sistemas de receta electrónica con Hadoop ..................... 7 1.2. OBJETIVOS DEL PROYECTO ............................................................................................................. 7 1.3. ORGANIZACIÓN DEL DOCUMENTO ................................................................................................... 8 2. ESPECIFICACIÓN DE REQUISITOS .............................................................................................. 10 2.1. CASOS DE USO ........................................................................................................................... 10 2.1.1. Diagrama de casos de uso............................................................................................... 10 2.1.2. Descripción de Actores .................................................................................................... 10 2.1.3. Descripción de casos de uso ............................................................................................ 11 2.2. REQUISITOS DE DIFUSIÓN DE LA INFORMACIÓN................................................................................. 13 2.3. REQUISITOS DE CARGA Y ALMACENAMIENTO .................................................................................... 14 2.4. REQUISITOS DE ARQUITECTURA Y PLATAFORMA ................................................................................ 15 2.5. MATRIZ DE TRAZABILIDAD REQUISITOS-CASOS DE USO ....................................................................... 16 2.6. CRITERIOS DE VALIDACIÓN ........................................................................................................... 17 2.6.1. Exclusiones y asunciones del proyecto ............................................................................ 17 2.6.2. Entregables del proyecto ................................................................................................. 18 3. GESTIÓN DEL PROYECTO .......................................................................................................... 19 3.1. METODOLOGÍA DE TRABAJO ......................................................................................................... 19 3.2. PLANIFICACIÓN .......................................................................................................................... 20 3.3. ESTIMACIÓN DE COSTES ............................................................................................................... 23 3.4. ANÁLISIS DE RIESGOS .................................................................................................................. 25 3.4.1. Control y seguimiento de riesgos .................................................................................... 29 3.5. GESTIÓN DE LA CONFIGURACIÓN ................................................................................................... 29 3.5.1. Elementos e configuración .............................................................................................. 29 Introducción Página 3 de 123 4. ANÁLISIS TECNOLÓGICO ........................................................................................................... 32 4.1. BIG DATA ................................................................................................................................. 32 4.1.1. Las siete V´s del Big Data ................................................................................................ 32 4.1.2. Características comunes.................................................................................................. 34 4.1.3. Modelos de computación ................................................................................................ 35 4.2. HADOOP .................................................................................................................................. 37 4.2.1. Hadoop Distributed File System ...................................................................................... 38 4.2.2. Hadoop MapReduce ........................................................................................................ 42 4.2.3. Distribuciones .................................................................................................................. 47 4.2.4. Ecosistema Hadoop ......................................................................................................... 49 4.3. SISTEMA DE DISPENSACIÓN ELECTRÓNICA ....................................................................................... 62 4.3.1. Arquitectura .................................................................................................................... 63 4.3.2. Formato de los logs ......................................................................................................... 63 4.4. VIRTUALIZACIÓN ........................................................................................................................ 65 4.4.1. Docker ............................................................................................................................. 65 5. DISEÑO ..................................................................................................................................... 69 5.1. ARQUITECTURA GENERAL DEL SISTEMA ........................................................................................... 69 5.2. ARQUITECTURA DEL SISTEMA DE PROCESAMIENTO DE LOG .................................................................. 69 5.2.1. Arquitectura Lambda ...................................................................................................... 69 5.2.2. Arquitectura alternativa .................................................................................................. 74 5.2.3. Software de procesamiento ............................................................................................ 80 5.3. NODOS SISTEMA DE DISPENSACIÓN ELECTRÓNICA ............................................................................ 81 5.4. NODOS DEL CLÚSTER HADOOP ...................................................................................................... 83 5.5. SISTEMA DE MONITORIZACIÓN ...................................................................................................... 84 5.6. APLICACIÓN WEB ....................................................................................................................... 84 5.6.1. Operaciones por unidad de tiempo ................................................................................. 86 5.6.2. Uso del sistema por operación ........................................................................................ 86 Introducción Página 4 de 123 6. IMPLEMENTACIÓN ................................................................................................................... 88 6.1. DESPLIEGUE Y CONFIGURACIÓN DEL CLÚSTER ................................................................................... 88 6.1.1. Permitir reanudar el clúster ............................................................................................ 88 6.1.2. Soporte para realizar imágenes sobre el estado actual del clúster ................................. 90 6.1.3. Automatización de la instalación de los servicios en el clúster ....................................... 90 6.1.4. Instalación y configuración de servicios adicionales ....................................................... 91 6.2. SISTEMA DE DISPENSACIÓN ELECTRÓNICA ....................................................................................... 95 6.3. SISTEMA DE PROCESAMIENTO ....................................................................................................... 97 6.4. DEFINICIÓN DE INFORMES ............................................................................................................ 99 7. PRUEBAS ................................................................................................................................ 104 7.1. DEFINICIÓN DEL ESCENARIO DE PRUEBAS ....................................................................................... 104 7.1.1. Equipo de pruebas ......................................................................................................... 104 7.1.2. Datos de prueba ............................................................................................................ 104 7.2. CAPA DE RECOLECCIÓN .............................................................................................................. 105 7.3. CAPA DE PROCESAMIENTO ......................................................................................................... 108 7.4. RESULTADOS ........................................................................................................................... 108 8. CONCLUSIONES ...................................................................................................................... 113 8.1. AMPLIACIONES ........................................................................................................................ 114 9. ANEXOS .................................................................................................................................. 116 9.1. INSTALACIÓN DOCKER ............................................................................................................... 116 9.1.1. Prerrequisitos ................................................................................................................ 116 9.1.2. Instalación ..................................................................................................................... 116 9.2. ANONIMIZAR LOG REALES .......................................................................................................... 118 9.3. DESPLIEGUE DEL SISTEMA .......................................................................................................... 120 10. BIBLIOGRAFÍA ........................................................................................................................ 122 Introducción Página 5 de 123 1. Introduccio n En el presente documento se recoge la memoria del Trabajo Fin de Grado de los estudios de Grado en Ingeniería Informática realizados en la Escuela Técnica Superior de Ingeniería de la Universidad de Santiago de Compostela. Este proyecto nace como una ampliación al Trabajo Fin de Grado presentado en septiembre de 2014 por Andrea Vila Rodríguez titulado “Análisis de logs de actividad en sistemas de Receta Electrónica con Hadoop”. 1.1. Contexto El desarrollo del proyecto está ligado al Observatorio Tecnológico HP-USC que surge de un convenio de colaboración entre la empresa Hewlett-Packard y la Universidad de Santiago de Compostela. Como ya hemos comentado, este proyecto pretende ampliar las capacidades de un trabajo presentado previamente que también ha sido realizado bajo el amparo del Observatorio Tecnológico. La colaboración con la empresa ha sido de vital importancia puesto que el presente proyecto está íntimamente ligado con el ámbito funcional de la Receta Electrónica, en el que HP presta servicios a varias Comunidades Autónomas. En concreto, nos centraremos en el sistema de Dispensación Electrónica (DISEL) que está actualmente implantado en el Servicio Galego de Saúde (SERGAS) y con cuyo equipo de desarrollo mantendremos un contacto constante. Los sistemas de Receta Electrónica permiten a los facultativos realizar prescripciones y dispensar fármacos de manera electrónica, eliminando de este modo el uso de la receta en papel y descongestionando la actividad asistencial y el proceso de citación en los centros de salud. Además, podemos clasificar el sistema desarrollado dentro del mundo del Big Data, un sector en plena expansión con un gran potencial por explotar y en el que HP cuenta con un gran número de profesionales que han servido de apoyo en la realización del proyecto. 1.1.1. HP Hewlett-Packard es un proveedor de soluciones tecnológicas para consumidores, empresas e instituciones de todo el mundo. Las ofertas de la empresa abarcan las áreas de infraestructura de tecnologías de la información (TI), informática personal y dispositivos de acceso, servicios globales y tratamiento de imágenes e impresión. El objetivo fundamental de HP es crear, diseñar y ofrecer soluciones tecnológicas que impulsen el valor empresarial, creen valor social y mejoren las vidas de los clientes. HP vende sus productos y servicios en más de 170 países y cuenta con aproximadamente 304.000 empleados en todo el mundo. Las oficinas centrales de HP se encuentran en Palo Alto, California. HP cuenta con tres grupos de negocio principales, cada uno de los cuales se encarga de impulsar el desarrollo y la venta de productos y servicios relacionados con mercados concretos: - El Grupo de Sistemas Personales (GSP) saca al mercado PCs para uso personal y empresarial, dispositivos de computación móviles y estaciones de trabajo de HP. - El Grupo de Impresión y Tratamiento de Imágenes (IPG) aplica su saber hacer a la impresión por inyección de tinta, LaserJet y comercial, suministros de impresión, fotografía digital y entretenimiento. Introducción Página 6 de 123 - HP Enterprise Business dispone de una cartera de clase mundial de productos empresariales incluyendo servidores, almacenamiento, productos de red, servicios de externalización y software. Estas unidades comparten funciones centrales, como investigación y desarrollo (I+D), cuentan con una estructura flexible para aprovechar eficazmente las oportunidades conjuntas, y están vinculadas por comunicaciones y procesos comunes que permiten prestar un servicio perfecto y ofrecer un mensaje uniforme a los clientes. El desarrollo de este proyecto está ligado al área HP Analytics and Data Management como parte del grupo de negocio HP Enterprise Services. HP Enterprise Services es una organización mundial de consultoría que ofrece servicios de TI, abarcando productos y tecnología tanto de HP como de terceros. Los consultores de HP Enterprise Services tienen probada experiencia en el diseño de soluciones extremo a extremo adecuadas para cada cliente. El hecho de que inviertan el tiempo necesario en entender los requerimientos del cliente, de sus negocios y de sus mercados, hace que sus esfuerzos tengan resultados eficaces, con mínimos riesgos y en el menor tiempo posible. HP ha desarrollado un completo set de servicios que abarca todo el ciclo de TI, desde el diseño y la planificación hasta la implementación, mantenimiento y operación. El diverso portfolio de servicios de HP Enterprise Services incluye tanto soluciones de negocio como servicios tecnológicos dentro del nuevo estilo de TI y está organizado entorno a las siguientes siete prácticas que se muestran en la Figura 1.1: Figura 1.1: HP Enterprise Services En Galicia cuenta con un Centro de Excelencia de BI en Santiago de Compostela y colabora con la Universidad de Santiago de Compostela a través del Centro Singular de Investigación en Tecnoloxías da Información (CiTIUS) y con acuerdo de tutela de Proyectos Fin de Carrera del Grado y Master en Ingeniería Informática. HP Analytics and Data Management (A&DM) forma parte de HP Enterprise Services. Los servicios A&DM facilitan el alineamiento entre las personas, los procesos y las tecnologías más adecuadas para crear las analíticas avanzadas y las estrategias de gestión de datos que necesitan los clientes. Los consultores proporcionan el consejo y el soporte necesario para transformar, gestionar y desarrollar iniciativas de Big Data que permitan a los clientes identificar y explotar nuevas Introducción Página 7 de 123 oportunidades que aporten un valor añadido a sus organizaciones. El portfolio específico de A&DM se estructura en las siguientes líneas estratégicas: - Consejo: allanar el camino hacia la innovación con sesiones de trabajo personalizadas sobre Big Data e inteligencia de negocio, evaluaciones de la situación actual y entornos de descubrimiento de oportunidades. - Transformación: transformar la información en conocimiento orientado a la acción mediante el desarrollo y despliegue de analíticas avanzadas. - Gestión: gobernanza y gestión de los datos como un activo estratégico a lo largo de todo el ecosistema de información, mediante métodos, procesos y tecnologías de eficacia probada. El portfolio de servicio de HP A&DM está además soportado por el conocimiento de tecnologías específicas tanto de HP (HP HAVEn, HP Vertica, HP Autonomy IDOL), como de sus partners y del ecosistema Free Open Source Software. 1.1.2. Análisis de log de actividad en sistemas de receta electrónica con Hadoop El presente proyecto surge como una ampliación del Trabajo Fin de Grado presentado, por Andrea Vila, en septiembre de 2014. En este trabajo se hacía una primera aproximación al problema y se proponía una solución que, partiendo de grandes cantidades de datos de log, era capaz de generar informes acerca de la actividad del sistema en un periodo de tiempo determinado. No se contemplaba el análisis en tiempo real a medida que se producen nuevos eventos, sino que partía de un conjunto de ficheros previamente generados. Este sistema permitía la realización de análisis periódicos en momentos en los que, por ejemplo, la carga del sistema era baja. De este modo, se añadía un retardo importante frente a un sistema de procesamiento en tiempo real puesto que una situación anómala no sería detectada hasta que se terminase el ciclo actual y se realizase el siguiente análisis. El aumento en las capacidades de cómputo disponibles hace asumible el desarrollo de un sistema de procesamiento en tiempo real, sobre todo, teniendo en cuenta los beneficios que puede aportar. La solución propuesta consistía, básicamente, en el acceso a los ficheros de log almacenados en HDFS (Hadoop Distributed File System) de forma estructurada a través de Hive. De este modo, se permitía el acceso a los datos mediante un lenguaje similar a SQL (HiveQL) que se utilizaba para la realización de consultas desde la herramienta de generación de informes Eclipse BIRT. Discutiremos estas tecnologías en la sección de análisis tecnológico. Esta primera aproximación, así como el gran análisis realizado, tanto del problema en concreto, como de un gran número de tecnologías disponibles suponen un excelente punto de partida para la realización de este proyecto. 1.2. Objetivos del proyecto El objetivo de este proyecto es proporcionar una herramienta capaz de analizar los logs de actividad de un sistema de Receta Electrónica en tiempo real, en concreto, del sistema de Dispensación Electrónica implantado en el SERGAS, de tal forma que los usuarios puedan tener a su disposición una serie de informes que pueden actualizar utilizando los parámetros que deseen. Especificación de requisitos Página 14 de 123 - Descripción: los usuario podrán acceder a los campos de las líneas de log originales disponibles de forma estructurada en una base de datos a través de consultas SQL. A continuación se detallan los elementos de difusión de la información que estarán de forma predeterminada en el sistema: Requisito RDI_004 - Título: informe 1: número de operaciones por franja horaria en el último día - Descripción: estará disponible un informe en el que se muestre una gráfica en la que se puede ver el número de operaciones por franja horaria durante el último día con el fin de identificar tendencias que puedan llevar el sistema a una situación de colapso o poder verificar si un fallo ha podido ser debido a un pico de uso inesperado. Requisito RDI_005 - Título: informe 2: número de operaciones por minuto durante la última hora - Descripción: estará disponible un informe en el que se muestre una gráfica en la que se puede ver el número de operaciones por minuto durante la última hora, se trata de un informe que complementa al informe definido en el requisito RDI_004. Requisito RDI_006 - Título: informe 3: uso del sistema desglosado por operación - Descripción: estará disponible un informe en el que se recoge el tiempo de procesamiento y el número de peticiones que se han realizado por cada tipo de operación en un periodo de tiempo determinado, que podrá seleccionar el usuario. Además de los informes generados acerca de la actividad del sistema de Dispensación Electrónica estará disponible información acerca de las estadísticas de ejecución de nuestro sistema: Requisito RDI_007 - Título: porcentaje de uso de los buffers - Descripción: se proporcionará un informe en el que se recoja la evolución de ocupación de los buffers de la capa de carga con el fin de poder detectar si se han llenado y, por lo tanto, ha habido pérdida de datos. Requisito RDI_008 - Título: número de eventos recibidos - Descripción: se debe mantener el número de eventos (líneas de log) que se están recibiendo con el fin de poder depurar el sistema y ver que coincide con el número de líneas procesadas. 2.3. Requisitos de carga y almacenamiento A continuación se describen los requisitos que definen la forma en que se cargarán los nuevos datos en el sistema y la forma en la que se deben almacenar: Requisito RCA_001 - Título: origen de la información Especificación de requisitos Página 15 de 123 - Descripción: el origen de la información serán las líneas de log que envía el sistema de Dispensación Electrónica en tiempo real a medida que se generan. Requisito RCA_002 - Título: no debe haber pérdida de datos con periodos de fallos del clúster inferiores a un día - Descripción: cuando los nodos del sistema de Dispensación Electrónica no puedan enviar los datos a los nodos del clúster Hadoop para ser procesados deberán ser almacenados y serán reenviados en el momento en el que se reestablezca la conexión. El periodo máximo en el que se almacenarán los datos para ser reenviados será de un día, a partir de este momento serán descartados. Conseguimos así que los nodos del sistema de Dispensación Electrónica no tengan que disponer de una gran capacidad de almacenamiento disponible para los datos de actividad y evitamos la pérdida de datos en la mayor parte de las ocasiones en las que pueda ocurrir un problema. Requisitos RCA_003 - Título: simular el sistema de Dispensación Electrónica - Descripción: a los efectos de este TFG se debe implementar una aplicación que simule el funcionamiento del sistema de Dispensación Electrónica a partir de los ficheros de log originales. De este modo, esta aplicación leerá los ficheros originales y enviará las líneas del mismo modo que lo haría el sistema original. Requisito RCA_004 - Título: utilizar datos anonimizados - Descripción: los ficheros de log contienen datos sensibles protegidos por la Ley Orgánica de Protección de Datos con lo que, a los efectos de este TFG, los datos deben ser anonimizados. Requisito RCA_005 - Título: mantener todo el histórico - Descripción: se debe mantener todo el histórico de los datos con lo que no se programarán borrados de datos. 2.4. Requisitos de arquitectura y plataforma Requisitos RAP_001 - Título: log4j - Descripción: la aplicación que simula el sistema de Dispensación Electrónica debe utilizar el framework log4j para registrar los nuevos eventos, el envío de estos datos al clúster Hadoop debe definirse a través de los ficheros de configuración de log4j. Requisito RAP_002 - Título: Hadoop - Descripción: el sistema de procesamiento de logs debe desplegarse en un clúster Hadoop. Requisito RAP_003 Especificación de requisitos Página 16 de 123 - Título: Pentaho Report Designer - Descripción: se debe proporcionar un mecanismo de configuración de la aplicación Pentaho Report Designer para que los usuarios puedan generar informes utilizando esta aplicación a partir de los datos presentes en el clúster Hadoop. Requisito RAP_004 - Título: Docker - Descripción: se desplegará el clúster en contenedores Docker en lugar de en máquinas virtuales convencionales con el fin de explorar las ventajas y desventajas que puede aportar este método de virtualización. Requisito RAP_005 - Título: memoria 8GB - Descripción: la plataforma en la que se ejecutará el clúster Hadoop y el software desarrollado en el presente proyecto contará con un máximo de 8GB de memoria RAM con el fin de exprimir al máximo el sistema en entornos con pocos recursos disponibles. Requisito RAP_006 - Título: utilización de software gratuito - Descripción: además de las tecnologías impuestas por los requisitos anteriores, se podrán utilizar otro tipo de soluciones para diferentes propósitos siempre y cuando cuenten con un tipo de licencia gratuita. 2.5. Matriz de trazabilidad requisitos-casos de uso A continuación mostraremos una matriz de trazabilidad en la que se relacionan los requisitos identificados con los casos de uso que hemos descrito anteriormente, esta relación se especifica con un “1” en la intersección de la columna del caso de uso con la fila del requisito. En esta matriz no hemos representado los requisitos de arquitectura y plataforma puesto que se trata de requisitos no funcionales con lo que no están directamente relacionadas con las funcionalidades que debe soportar el sistema (que vienen dadas por los casos de uso). Esto nos permitirá identificar fácilmente los cambios que supone una modificación en algunas de las funcionalidades. Especificación de requisitos Página 17 de 123 CU-01: Consultar informes predefinidos CU-02: Generar nuevos informes CU-03: Acceder a los datos de actividad originales CU-04: Revisar estadísticas del sistema CU-05: Registrar evento RDI_001: creación de informes predefinidos como medio de difusión de la información a través de la aplicación web 1 RDI_002: posibilidad de crear nuevos informes 1 1 1 RDI_003: acceso a los datos originales sin procesar 1 1 1 RDI_004: informe 1: número de operaciones por franja horaria en el último día 1 1 RDI_005: informe 2: número de operaciones por minuto durante la última hora 1 1 RDI_006: informe 3: uso del sistema desglosado por operación 1 1 RDI_007: porcentaje de uso de los buffers 1 RDI_008: número de eventos recibidos 1 RCA_001: origen de la información 1 RCA_002: no debe haber pérdida de datos con periodos de fallos del clúster inferiores a un día 1 RCA_003: simular el sistema de Dispensación Electrónica 1 RCA_004: utilizar datos anonimizados 1 RCA_005: mantener todo el histórico 1 1 2.6. Criterios de validación A continuación se definen los criterios que se utilizarán para validar el resultado del presente proyecto así como las exclusiones y asunciones que se aplicarán en el desarrollo del mismo por no estar incluidas en la definición de los requisitos. Además, al final de esta sección, se definen los entregables del proyecto. 2.6.1. Exclusiones y asunciones del proyecto A los efectos de este Trabajo Fin de Grado, no se tendrán en cuenta cuestiones de seguridad y control de acceso al clúster Hadoop al entenderse que se trata de configuraciones propias del entorno de producción en el que se desplegará el sistema y que por tanto están definidas por las políticas de seguridad de la empresa. La configuración de un clúster independiente tiene como objetivo la realización de las pruebas y el análisis acerca de la utilización de contenedores Docker cómo sistema de virtualización en el marco del presente proyecto. Especificación de requisitos Página 18 de 123 El clúster sobre el que se despliegue el analizador de log en producción debe tener correctamente instalados y configurados todos los servicios necesarios que se describen en la presente memoria. Este despliegue en producción no se incluye en el desarrollo de este proyecto. El sistema cumplirá con las restricciones recogidas en los requisitos previamente descritos siempre y cuando la carga del sistema sea igual o inferior a la impuesta por los ficheros de log de ejemplo de los que se dispone para su desarrollo. 2.6.2. Entregables del proyecto Como resultado de la realización del presente proyecto se producirán los siguientes entregables: - La presente memoria en la que se recoge toda la documentación acerca del desarrollo y gestión del proyecto así como las conclusiones y resultados obtenidos. - Todos los ficheros de configuración y scripts utilizados para la instalación del entorno así como un manual que forma parte de la memoria. - El software encargado de realizar el procesamiento en tiempo real, incluido el código fuente. - Una aplicación web que se conecta al clúster Hadoop y produce una serie de informes, código fuente incluido. Describiremos en mayor detalle todos los ficheros que conforman los entregables del proyecto en la sección de gestión de la configuración. Gestión del proyecto Página 19 de 123 3. Gestio n del proyecto En este capítulo se detallan todos los procesos propios de la gestión de proyectos que sirven de marco de trabajo para abordar el desarrollo del proyecto con garantías. En primer lugar, definiremos una metodología de trabajo fundamentada en la propuesta por HP para el desarrollo de proyectos dentro del ámbito del business intelligence, esto nos proporcionará una base sólida y testada por un gran número de profesionales del sector. A continuación, propondremos una planificación temporal del trabajo basada en dicho ciclo de vida. Por último, realizaremos una estimación de costes y un análisis de riesgos. Como resultado, obtendremos una visión global del proyecto, sobre todo, centrándonos en temas de vital importancia como los plazos de finalización y los costes derivados de su desarrollo así como los riesgos asociados que pueden llevar a que el proyecto no finalice con éxito. Se trata de información de vital importancia a la hora de decidir si el proyecto es viable o, por lo contrario, está abocado al fracaso. 3.1. Metodología de trabajo Como ya hemos comentado, uno de los primeros pasos a la hora de afrontar un nuevo proyecto consiste en definir una metodología de trabajo clara que se llevará a cabo durante todo el desarrollo del mismo. A continuación, describiremos en detalle la que hemos seleccionado para la realización de este proyecto. Utilizaremos la metodología desarrollada por HP para llevar a cabo proyectos relacionados con el mundo de la inteligencia de negocio [1] denominada HPGM-BII (HP Global Method for BI Implementation). Se trata de una metodología basada en la experiencia de HP a nivel mundial gestionando información del orden de terabytes, ofreciendo un enfoque repetitivo e iterativo, de manera coherente y aplicando las mejores prácticas para resolver problemas complejos. En la figura 3.1 se puede ver un esquema acerca de las fases de esta metodología. Figura 3.1: Metodología HPGM-BII Las fases que describe esta metodología se organizan de forma similar a un ciclo de vida en cascada, no obstante, no se realizan de manera secuencial sino que se ejecutan de forma iterativa solapando, en muchos casos, unas fases con otras. En la figura 3.2 se ofrece una visión general de esta metodología: Definición Requisitos Análisis Arquitectura Diseño Desarrollo Pruebas Despliegue Uso Gestión del proyecto Página 20 de 123 Figura 3.2: HPGM-BII A continuación se detallan las características fundamentales de este modelo: - Claridad en los objetivos funcionales: para asegurar la entrega de valor a la organización se definen unos estatutos de proyecto que proporcionan una definición clara del proyecto, objetivos, alcance, hipótesis, etc. - Desarrollo iterativo: el desarrollo se realiza de manera iterativa para asegurar la calidad de los requisitos capturados. En cada iteración se valora el estado del proyecto con el cliente y se marcan los siguientes pasos a seguir para cumplir con los requisitos. - Implicación del cliente: el cliente está profundamente involucrado en el desarrollo del proyecto. La creación de prototipos implica a los usuarios desde las fases iniciales del desarrollo. - Pruebas de aceptación: el desarrollo se realiza centrado en pruebas de aceptación de usuario para verificar el alineamiento con las expectativas. De esta forma se garantiza en todo momento el cumplimiento de las funcionalidades requeridas, evitando posteriores errores de implementación. 3.2. Planificación A continuación describiremos la planificación que hemos realizado para el desarrollo del proyecto. Al tratarse de un Trabajo Fin de Grado se dan una serie de circunstancias muy especiales que no son comunes en el desarrollo de proyectos informáticos. En primer lugar, el grueso del trabajo lo realiza una única persona que hace todas las tareas de gestión y desarrollo en lugar de un equipo de trabajo completo. Por otro lado, los tutores del proyecto juegan un doble papel, por un lado hacen el rol del cliente y por otro lado supervisan todas las tareas que se están llevando a cabo ejerciendo de jefes de proyecto. Todas estas circunstancias hacen que sea necesario adaptar nuestra metodología a esta situación tan especial. En todo caso, mantendremos las líneas maestras que la definen. Realizaremos pruebas de aceptación durante todas las fases del proyecto por parte de los tutores. La implicación del cliente en el desarrollo del proyecto está ligado al punto anterior puesto que, como ya comentamos, ambos roles recaen sobre los tutores. Con respecto a la claridad en los objetivos, en la Gestión del proyecto Página 21 de 123 presente memoria se detallan tanto los objetivos como los requisitos que debe cumplir el sistema, también se añade información acerca de las restricciones y las asunciones que se han realizado a la hora de desarrollar el proyecto. Sin embargo, el solapamiento de tareas que propone HPGM-BII se hace especialmente complicado debido a que la mayor parte de las mismas las realiza una única persona. Además, el proyecto desarrollado en el presente Trabajo Fin de Grado se puede considerar, realmente, como un incremento dentro de un proyecto mayor cuyo primer incremento ha sido el Trabajo Fin de Grado ya comentado que se ha presentado en septiembre de 2014. Esto ha permitido que tanto la definición de los objetivos como la especificación de los requisitos que debería cumplir este nuevo incremento fuese muy clara desde el inicio. Las principales fases en las que se ha dividido el trabajo son las siguientes: - Definición del proyecto: en esta primera etapa se sientan las bases del proyecto fijando los objetivos generales que se pretenden abordar, en este caso se toma como base el Trabajo Fin de Grado anterior con el fin de identificar las nuevas características que se quieren añadir al sistema. Una de las principales misiones de esta fase es la elaboración del anteproyecto que servirá de guía en la posterior realización del proyecto. - Análisis del proyecto: en esta etapa se realizan todas las tareas de análisis incluyendo la especificación de requisitos, el análisis de costes y el análisis de riesgos. Además, se estudian las tecnologías que se barajarán como alternativas a la hora de implementar el sistema. - Diseño: en base al análisis previo realizaremos una propuesta de diseño tanto a nivel de arquitectura del sistema como a un nivel de detalle más bajo en el que se definen como serán implementados todos los módulos del sistema. - Instalación del entorno: esta fase se dedica a la instalación del entorno y a crear un manual que permita reproducir esta instalación en el futuro. - Desarrollo del sistema: en esta etapa se desarrolla el producto final definido previamente en las etapas de análisis y diseño. - Pruebas: llevaremos a cabo una serie de pruebas que nos permitan validar el desarrollo realizado en la etapa anterior frente a los requisitos previamente definidos. Esta etapa supone la ejecución del sistema mediante la utilización de una serie de datos de prueba que nos permitan ver que realmente se obtienen los resultados esperados. - Documentación: en esta etapa se realiza la memoria del proyecto, cabe destacar que a pesar de que aparezca al final de forma independiente, esta tarea es transversal a todas las demás, con el fin de mantener la lista de tareas siguiente los más simple y legible posible la recogeremos al final como una única tarea. No obstante, hay que tener en cuenta que, efectivamente, gran parte del esfuerzo se realiza al final del proyecto puesto que se integran todas las partes ya redactadas y se prepara para la entrega final. A continuación se puede ver la planificación completa en la que se muestran todas las tareas que se han llevado a cabo a lo largo del proyecto: Nombre de tarea Duración Comienzo Fin Definición del proyecto 11 días lun 02/02/15 lun 16/02/15 Reunión inicial 1 día lun 02/02/15 lun 02/02/15 Elaboración anteproyecto 5 días mar 03/02/15 lun 09/02/15 Gestión del proyecto Página 22 de 123 Validación anteproyecto 5 días mar 10/02/15 lun 16/02/15 Entregar anteproyecto 0 días lun 16/02/15 lun 16/02/15 Análisis del proyecto 24 días mar 17/02/15 lun 23/03/15 Análisis de requisitos 3 días mar 17/02/15 jue 19/02/15 Análisis de costes 2 días vie 20/02/15 lun 23/02/15 Análisis de riesgos 2 días mar 24/02/15 mié 25/02/15 Análisis tecnológico 17 días mié 25/02/15 lun 23/03/15 Estudio de las tecnologías 12 días jue 26/02/15 vie 13/03/15 Selección tecnológica 5 días lun 16/03/15 lun 23/03/15 Análisis finalizado 0 días mié 25/02/15 mié 25/02/15 Diseño 14 días mar 24/03/15 mar 14/04/15 Definir arquitectura del sistema 4 días mar 24/03/15 vie 27/03/15 Diseño de la capa de obtención de datos 2 días lun 30/03/15 mar 31/03/15 Diseño de la capa de procesamiento 1 día mié 01/04/15 mié 01/04/15 Diseño de la capa de almacenamiento 1 día lun 06/04/15 lun 06/04/15 Diseño de la aplicación web 1 día mar 07/04/15 mar 07/04/15 Validar diseños 5 días mié 08/04/15 mar 14/04/15 Diseño finalizado 0 días mar 14/04/15 mar 14/04/15 Instalación del entorno 10 días mié 15/04/15 mar 28/04/15 Instalación y configuración de Docker 2 días mié 15/04/15 jue 16/04/15 Instalación y configuración del clúster Hadoop 5 días vie 17/04/15 jue 23/04/15 Instalación de servicios necesarios en el clúster 3 días vie 24/04/15 mar 28/04/15 Instalación finalizada 0 días mar 28/04/15 mar 28/04/15 Desarrollo del sistema 22 días mié 29/04/15 lun 01/06/15 Anonimización de los logs de prueba 4 días mié 29/04/15 mar 05/05/15 Desarrollo del sistema de procesamiento 9 días mié 06/05/15 mar 19/05/15 Desarrollo del sistema de almacenamiento 3 días mié 20/05/15 vie 22/05/15 Scripts de creación de vistas 2 días mié 20/05/15 jue 21/05/15 Consultas SQL para la generación de informes 1 día vie 22/05/15 vie 22/05/15 Aplicación web 6 días lun 25/05/15 lun 01/06/15 Generación de definición de los informes 2 días lun 25/05/15 mar 26/05/15 Conexión con la definición de los informes 2 días mié 27/05/15 jue 28/05/15 Interfaz de usuario 2 días vie 29/05/15 lun 01/06/15 Desarrollo finalizado 0 días lun 01/06/15 lun 01/06/15 Pruebas 13 días mar 02/06/15 vie 26/06/15 Configuración entorno de pruebas 5 días mar 02/06/15 lun 08/06/15 Programación de ejecución 1 día mar 09/06/15 mar 09/06/15 Análisis de resultados 2 días mié 10/06/15 jue 11/06/15 Validación de Resultados 5 días vie 12/06/15 vie 26/06/15 Pruebas finalizadas 0 días vie 26/06/15 vie 26/06/15 Documentación 17 días lun 29/06/15 mar 21/07/15 Redacción de la memoria 12 días lun 29/06/15 mar 14/07/15 Elaboración de la presentación pública 1 día mié 15/07/15 mié 15/07/15 Corrección memoria 5 días mié 15/07/15 mar 21/07/15 Documentación finalizada 0 días mar 21/07/15 mar 21/07/15 Gestión del proyecto Página 23 de 123 A continuación se puede ver una gráfica en la que se muestra la disponibilidad de los participantes en el proyecto tras la asignación de las tareas anteriores teniendo en cuenta una jornada laboral de 8 horas. Ambos tutores (Tomás Fernández Pena y Adolfo Sanz Anchelergues) mantienen la misma disponibilidad puesto que se les han asignado las mismas tareas de supervisión, en todo caso, esta disponibilidad se mantiene alta con un mínimo al final del desarrollo del proyecto coincidiendo con las tareas de corrección de la memoria y validación del proyecto. En caso del alumno (Daniel Cores Costa) se ha respetado un periodo en el que se ha asignada una menor carga de trabajo (manteniendo una disponibilidad más alta) debido a la realización de las prácticas en empresa. Además, durante el mes de mayo se ha reducido la carga de trabajo coincidiendo con la época de exámenes. De este modo, se pretende buscar la menor interferencia posible con las demás tareas del grado en las que el alumno está involucrado. Figura 3.3: Disponibilidad del equipo 3.3. Estimación de costes A continuación mostraremos la estimación de costes del proyecto desglosada por costes de personal, costes de materiales y otros costes asociados al proyecto. Costes de personal: la estimación de costes de personal se ha realizado en base a un estudio realizado por la empresa “Vitae Consultores” acerca de la situación salarial del sector TIC en Galicia en los años 2014-2015 del que obtendremos los salarios de cada uno de los roles que intervienen en el proyecto. En el caso del alumno se le ha asignado un rol de analista programador con una experiencia de entre 0 y 2 años, si cogemos el salario medio de esta categoría, obtenemos 16.000€/año, lo que supone 8.33€/hora. Por otro lado hemos asignado el rol de Jefe de Proyecto con más de 8 años de experiencia a los tutores. Obtenemos un salario medio de 40.000€/año, lo que supone 20,83€/hora. Cabe destacar que se trata, en ambos casos, de salarios brutos. A mayores debemos añadir los gastos asociados a la cuota de la Seguridad Social que debe abonar la empresa y que supone un 30% del salario de cada empleado, obteniendo unos valores finales de 27€/hora en el caso de los Jefes de proyecto y de 10€/hora en el caso del analista programador. 0 horas 10 horas 20 horas 30 horas 40 horas 50 horas 60 horas 70 horas 80 horas 90 horas Disponibilidad restante (Daniel Cores Costa) Disponibilidad restante (Tomás Fernández Pena) Disponibilidad restante (Adolfo Sanz Anchelergues) Gestión del proyecto Página 30 de 123 o Proyecto con la aplicación de monitorización de los agentes Flume o Scripts de anonimizado de los datos originales - Memoria del proyecto - Scripts bash para desplegar el clúster - Imágenes Docker o Imagen base para los contenedores del clúster o Imagen del sistema de simulación del sistema de Dispensación Electrónica o Imagen para el contenedor en el que se desplegará la aplicación web A continuación, identificaremos el árbol de directorios de nuestro repositorio principal en el que se mantendrán todos los elementos de configuración identificados anteriormente y que coincidirá con la estructura de fichero de los entregables adjuntos a este proyecto. A lo largo de la presente memoria, sobre todo, en la sección de implementación se describirán estos elementos en un mayor nivel de detalle. Elemento Descripción TFG_030915 Carpeta raíz en la que se incluyen todos los ficheros MEM_TFG_030915.pdf Documento que recoge la presente memoria anonimizar.py Script Python utilizado para anonimizar los datos imgDISEL Carpeta que contiene los ficheros necesarios para la generación de la imagen que simula el funcionamiento del sistema de Dispensación Electrónica Dockerfile Fichero de definición de la imagen Docker flume.sh Fichero que lanza los agentes Flume flumeDisel.conf Fichero de configuración del agente Flume disel.jar Aplicación Java que simula el funcionamiento del sistema de Dispensación Electrónica apache-flume-1.6.0-bin Distribución de Flume que utilizaremos imgReporting Carpeta que contiene los ficheros necesarios para la generación de la imagen que contiene la aplicación web de generación de informes Dockerfile Fichero de definición de la imagen Docker Reporting.war Aplicación web hdp-docker Carpeta en la que se incluyen todos los ficheros relacionados con el clúster Hadoop imagen Carpeta que contiene los ficheros necesarios para la generación de la imagen del clúster Hadoop Dockerfile Fichero de definición de la imagen Docker hdp-cluster.sh Script que contiene el código necesario para automatizar el despliegue del clúster compartida Carpeta cuyo contenido se debe copiar a /usr/hdp y que será utilizada por os contenedores como almacenamiento compartido resources Carpeta con ficheros de configuración Gestión del proyecto Página 31 de 123 config.properties Fichero de configuración del sistema de procesamiento de log ambari-shell.sh Script que ejecuta el los comandos recogidos en ambari-script en la consola de Ambari para automatizar la instalación del clúster ambari-script Script con comandos Ambari para la instalación de todos los componentes hdp-blueprint Blueprint con la definición del clúster join-cluster.sh Script que reconfigura el agente Serf para volver a unir el agente al clúster spark-install.sh Script de instalación de Spark en el clúster analizador_1.0.jar Aplicación de procesamiento de log en tiempo real codigo Carpeta en la que se encuentra el código fuente procesamientoLog Carpeta que contiene el código del sistema de procesamiento de log aplicaciónWeb Carpeta que contiene el código de la aplicación web simulacionDISEL Carpeta que contiene el código que simula el funcionamiento del sistema de Dispensación Electrónica monitoringFlume Carpeta que contiene el código de la aplicación que utilizaremos para monitorizar los agentes Flume. Análisis tecnológico Página 32 de 123 4. Ana lisis tecnolo gico En el siguiente apartado realizaremos una contextualización tecnológica del proyecto así como un estudio de las diversas tecnologías que se han barajado a la hora de implementar el sistema final. Este estudio servirá de punto de partida para la realización, posteriormente, de una selección tecnológica teniendo en cuenta, por un lado, las características de cada una de estas tecnologías y, por otro lado, las necesidades específicas de nuestro proyecto. Las tecnologías seleccionadas así como la forma en que se interconectan y el rol que jugarán en la implementación final se describirán en el apartado de diseño, concretamente, en la sección de “5.2. Arquitectura del sistema de procesamiento de log”. 4.1. Big Data El concepto de Big Data [2] se refiere a toda aquella información que, debido a su gran tamaño y complejidad, no puede ser procesada o analizada utilizando procesos y herramientas tradicionales. La cantidad de datos generados, así como su naturaleza, ha cambiado radicalmente desde la época de las primeras mainframes hasta la actualidad. Este gran cambio se puede atribuir, en gran medida, al auge de la computación ubicua así como a la aparición de nuevos paradigmas como la web 2.0, las redes sociales, la computación en la nube o la popularización de las arquitecturas basadas en SaS (Software-as-a-Service). Cabe destacar, que el concepto de Big Data no se refiere exclusivamente a grandes cantidades de información sino que también se centra en la complejidad de los conjuntos de datos manejados, normalmente con estructuras muy heterogéneas (incluso textos en lenguaje natural carentes de estructura) que dificultan su procesamiento. La información que poseen las organizaciones es de vital importancia como herramienta principal a la hora de realizar la toma de decisiones y establecer nuevas líneas de negocio, el reto radica en recolectar, almacenar y procesar las grandes cantidades de información que se están generando de forma continua para poder aportar valor añadido a la organización. Todo ello, debe realizarse utilizando sistemas escalables y con un coste asumible para estas organizaciones, no es factible aumentar drásticamente los recursos hardware en cortos periodos de tiempo, en los que el volumen y complejidad de los datos manejados es muy probable que si se incremente [3]. 4.1.1. Las siete V´s del Big Data Como ya hemos comentado, Big Data no se refiere exclusivamente a grandes cantidades de datos, sino que entran en juego otros conceptos como son la variedad y la velocidad que forman junto con el volumen lo que se dio a conocer como las 3 V´s del Big Data [4]. Posteriormente, se han añadido otros dos conceptos fundamentales: valor y veracidad, dando lugar a las 5 V´s. - Volumen: se refiere a las grandes cantidades de datos que las organizaciones deben manejar. Cabe destacar que el ritmo al que crece la generación de nuevos datos se ha disparado en los últimos años, de tal forma, que se estima que el 90% del total de los datos existentes en el mundo han sido creados en los últimos 2 años. Según los datos publicados por YouTube cada minuto se suben unas 300 horas de vídeo a este sitio web. Por otro lado, según www.internetlivestats.com el tráfico total de Internet asciende a 29.000 GB por segundo. En las estadísticas publicadas por el CERN se recoge que el LHC genera más de 30 PB de datos al año y se mantienen un total de 100 PB almacenados de forma permanente en cinta. Análisis tecnológico Página 33 de 123 - Variedad: en el pasado, la mayor parte de los datos que manejábamos eran casi exclusivamente estructurados, entendiendo como tales todos aquellos conjuntos de datos cuya estructura viene definida por un esquema, y encajaban perfectamente en un modelo de base de datos relacional. En la actualidad, más de un 80% de los datos son no estructurados (texto, imágenes, video, etc.). De este modo, se presentan los sistemas Big Data, capaces de manejar datos estructurados, no estructurados y semiestructurados, como una alternativa a los sistemas tradicionales. Además, los sistemas Big Data no solo soportan todos estos tipos de datos, sino que permiten trabajar simultáneamente con varios de ellos, probablemente, procedentes de fuentes muy variadas. Un ejemplo de datos no estructurados lo tenemos en los textos en lenguaje natural, según los datos ofrecidos por la propia Twitter se publican unos 500 millones de Tweets por día, esto da una idea de la cantidad de datos no estructurados que posee Twitter. Otro claro ejemplo lo tenemos en Facebook, en abril de 2014, se estimaba que esta red social contaba con una base de datos de 300 PB entre textos e imágenes y generaba un tráfico total de 600 TB/día. - Velocidad: la cantidad de datos que se genera por segundo y que las organizaciones tienen que almacenar, procesar y dar respuesta puede llegar a ser muy alta, esto supone un reto para todos aquellos sistemas que tengan necesidades en tiempo real. En www.internetlivestats.com publican que se realizan unas 50.000 búsquedas en Google por segundo a las que el motor de búsqueda debe dar una respuesta prácticamente inmediata. - Veracidad: hace referencia a la fiabilidad asociado a ciertos tipos de datos. Las técnicas de Big Data deben aceptar la incertidumbre asociada a determinados datos como pueden ser las previsiones meteorológicas, los factores económicos o las intenciones de compra de futuros clientes. Es fundamental poder averiguar la calidad y la coherencia de los datos manejado con el fin de poder identificar la validez de los resultados obtenidos a partir de los mismos. Por ejemplo, una herramienta que analice el correo electrónico que recibe un usuario debe tener en cuenta que una parte de este correo es spam. En la web www.internetlivestats.es también ofrecen estadísticas acerca del uso global del correo electrónico, calculan que de los alrededor de 2.500.000 emails que se envían por segundo el 67% es spam. - Valor: se trata del objetivo último de estos sistemas, extraer valor a partir de un conjunto de datos. De nada vale poder acceder de forma eficiente a una gran cantidad de datos totalmente heterogéneos si no es posible extraer alguna conclusión de los mismos. Un claro ejemplo lo tenemos en el modelo de negocio de Facebook, que a partir de los datos recolectados a cerca de sus usuarios es capaz de ofrecer una audiencia segmentada, atendiendo a multitud de criterios, a la que las empresas pueden dirigir sus anuncios. En los datos de facturación de 2014, Facebook ha destacado que su facturación por publicidad ha ascendido hasta 3.590 millones de dólares durante el último trimestre del año fiscal, un 58,4% más que en todo 2013. Algunos autores añaden a estas cinco dimensiones las dos siguientes completando así lo que se conoce como las 7 V´s del Big Data: Análisis tecnológico Página 34 de 123 - Variabilidad: atiende al significado que puedan tener los datos según el contexto, uno de los ejemplos más claros lo tenemos en los sistemas de procesamiento de lenguaje natural, ya que el significado de cada palabra está fuertemente influenciado por el contexto en el que se utiliza. - Visualización: normalmente, una vez los datos han sido analizados y procesados, es necesario mostrar los resultados de forma clara y comprensible. Un punto clave es el control de acceso, ya que permitir visualizar ciertos datos sensibles para la organización a personal no autorizado puede tener consecuencias nefastas. 4.1.2. Características comunes Las siguientes características son comunes a la mayoría de técnicas utilizadas en sistemas Big Data [5]: 4.1.2.1. Los datos se encuentran distribuidos en una gran cantidad de nodos Uno de los objetivos de las técnicas basadas en Big Data es la utilización de hardware de propósito general que permita aprovechar la infraestructura de procesamiento de datos con la que ya cuentan las organizaciones (commodity hardware). Cada uno de estos servidores, por sí solo, carece de la capacidad de almacenamiento y de la potencia necesaria para hacer frente al procesamiento de grandes cantidades de datos en un tiempo razonable. Esto impone la necesidad de adoptar una arquitectura distribuida en la que todos los servidores disponibles puedan ofrecer un sistema de procesamiento y almacenamiento conjunto. De este modo, se ofrece una capa lógica que permite al programador abstraerse de toda la gestión de la concurrencia y centrarse únicamente en el desarrollo de los algoritmos de procesamiento. Se consiguen minimizar los riesgos con respecto a un enfoque tradicional automatizando todas las tareas de distribución y fusión de los datos así como el tratamiento de fallos parciales. En la mayoría de los casos, sería impensable que una sola máquina tuviera la capacidad de almacenamiento necesaria para almacenar la totalidad de los datos, no obstante, este no es el único beneficio de adoptar una arquitectura distribuida. También tenemos la posibilidad de duplicar bloques de datos en diferentes máquinas con el fin de asegurar alta disponibilidad de los datos y tolerancia a fallos. Además, permite el procesamiento en paralelo de los datos, cada nodo procesa un subconjunto de los datos totales consiguiendo de este modo una mejora significativa en el rendimiento total. 4.1.2.2. Se mueven las aplicaciones hacia los datos en lugar de al contrario Dada una aplicación en la que los datos residen en varias máquinas, desde un punto de vista tradicional, se podría optar por una arquitectura en la que una aplicación que residente en un servidor consulta a través de la red los datos necesarios que se encuentran en las demás máquinas. Se trata de una visión centralizada de la capa de aplicación a pesar de que los datos se encuentran distribuidos, este enfoque se centra en la aplicación tomando los datos como un elemento auxilia. En un entorno Big Data, el coste de enviar los datos por la red puede no ser asumible, en su lugar, es la propia aplicación la que se transmite hacia el nodo en el que se encuentran los datos Análisis tecnológico Página 35 de 123 donde serán procesados. Además de perjudicar el rendimiento, la transmisión de grandes cantidades de datos puede colapsar la red originando fallos en el sistema. Se añade, de este modo, una cierta complejidad, ya que además de las aplicaciones es necesario mover todas las librerías con las que la aplicación tenga alguna dependencia. La mayor parte de los sistemas Big Data permiten desplegar las aplicaciones de forma centralizada ocultando toda esta complejidad asociada. 4.1.2.3. En la medida de lo posible, los datos se procesan localmente Se trata de una consecuencia directa de las dos características anteriores, nos encontramos en un entorno distribuido en el que las aplicaciones se mueven hacia los nodos en los que se encuentra los datos. Si además, tenemos en cuenta que los accesos a disco son mucho más eficientes que los accesos a través de la red obtenemos un sistema en el que las aplicaciones se mueven a los nodos para realizar todo el procesamiento de datos de forma local. No obstante, no siempre es posible acceder a todos los datos de forma local, las tareas se planifican de tal modo que se minimicen los accesos a través de la red. Un claro ejemplo lo tenemos en un gran número de aplicaciones en las que es necesario procesar los resultados intermedios producidos en paralelo por cada nodo para producir un resultado final, es necesario, por lo tanto, transmitir todos estos resultados parciales por la red. Este proceso, en la mayoría de los casos, supone un tiempo muy inferior al consumido por el resto del procesamiento en los nodos. 4.1.2.4. Se priman los accesos secuenciales sobre los accesos aleatorios Los accesos a disco son más eficientes que los accesos a través de la red, pero no todos los accesos a disco suponen el mismo tiempo. Los discos duros poseen un cabezal lector que se debe posicionar en la dirección en la que se empezará la lectura, una vez hecho esto se realiza una lectura secuencial de los datos. El tiempo de posicionamiento del cabezal no es para nada despreciable sino que supone una penalización importante sobre los tiempos de acceso. Tenemos, por lo tanto, que cuantos más posicionamientos sean necesarios (accesos aleatorios) tendremos un tiempo de acceso peor, mientras que si realizamos accesos secuenciales obtendremos un mejor rendimiento. En algunos sistemas en los que se busca ofrecer el máximo rendimiento se opta por realizar accesos totalmente secuenciales de disco y, posteriormente, se filtran los datos en la memoria principal. 4.1.3. Modelos de computación A continuación describiremos los modelos de computación más comunes dentro de las técnicas basadas en Big Data [5]. 4.1.3.1. Massively Parallel Processing (MPP) Database System Los sistemas que utilizan una aproximación basada en MPP dividen los datos en subconjuntos que puedan ser procesados de forma independiente y por lo tanto en paralelo en diferentes nodos. El punto clave de este sistema radica en cómo se dividen los datos para crear los diferentes conjuntos. Análisis tecnológico Página 36 de 123 Se trata de un parámetro de diseño que debe ser especificado de antemano dependiendo de cada caso. El criterio utilizado para dividir y repartir los datos entre los nodos del clúster determina, en gran medida, el rendimiento que puede alcanzar cada consulta ya que restringe el número de nodos que podrán trabajar en paralelo de forma simultánea. Se puede dar el caso en que un criterio de división de los datos haga que una consulta se ejecute de forma muy eficiente mientras que otra consulta se vea gravemente perjudicada. Con el fin de minimizar este efecto negativo se duplican los datos y se dividen bajo diferentes criterios: en cada caso se seleccionan los datos particionados bajo el criterio que mejores resultados pueda ofrecer. Entre los principales productos comerciales que implementan este concepto tenemos IBM Netezza y EMC Greenplum. 4.1.3.2. Sistemas de bases de datos “en memoria” Desde un punto de vista funcional, se trata de un sistema prácticamente idéntico al caso de los sistemas MPP. La principal diferencia radica en la implementación, estos sistemas se ejecutan en nodos con grandes cantidades de memoria principal en la que se precargan los datos. SAP HANA es un ejemplo de sistema cuyo funcionamiento se basa en este principio 4.1.3.3. MapReduce Se trata del modelo de programación utilizado en Hadoop con lo que lo describiremos en mayor detalle en los siguientes apartados en los que se analiza este framework en profundidad. Desde un punto de vista funcional, MapReduce necesita que el usuario defina dos procesos: map y reduce. Cada nodo planifica una tarea map, esta accede a los datos y produce pares clave/valor que serán procesados en la etapa reduce. Un número preestablecido de nodos ejecutan la función reduce combinando (mediante una función previamente definida) los valores intermedios asociados a cada clave. Finalmente, la salida se escribe en almacenamiento persistente. MapReduce sigue una arquitectura maestro/esclavo en la que el nodo maestro se encarga de todas las tareas de monitorización y control mientras que los nodos esclavos se encargan de la ejecución propiamente dicha. Profundizaremos en esta arquitectura en la descripción de la implementación que se realiza en Hadoop de este modelo. Uno de los principales problemas del modelo MapReduce radica en la poca idoneidad para ejecutar algoritmos iterativos, esto cobra especial importancia si tenemos en cuenta que la mayor parte de los algoritmos de análisis de datos pertenecen a este grupo. Este modelo aplicado a algoritmos iterativos requiere que cada una de las iteraciones se ejecute como una tarea MapReduce independiente, cada una de estas tareas coge los datos de almacenamiento persistente y vuelca los resultados, de nuevo, en almacenamiento persistente. Esto, en la mayoría de los casos, genera un gran número de accesos innecesarios a disco ya que, potencialmente, los datos que una iteración recibe como entrada se pueden corresponder con la salida de la anterior. Análisis tecnológico Página 37 de 123 4.1.3.4. Bulk Synchronous Parallel (BSP) Se trata de un concepto similar a MapReduce. BSP añade una barrera de sincronización en la que todos los procesos (similares a los procesos map de MapReduce) envían datos al nodo maestro e intercambian información relevante sobre la ejecución. Una vez que todos los procesos han terminado (se ha completado una iteración) el nodo maestro indica a cada nodo de procesamiento que puede continuar con la siguiente iteración. La utilización de barreras de sincronización es muy común dentro de los paradigmas de computación paralela y, en este caso, se utiliza con el fin de paliar las deficiencias de rendimiento que presenta MapReduce ante algoritmos iterativos. Podemos encontrar proyectos dentro de la Fundación Apache como Hama o Giraph que implementan este modelo. 4.2. Hadoop Apache Hadoop [6] es un framework para el desarrollo de sistemas capaces de procesar grandes cantidades de datos utilizando modelos simples de programación. Fue diseñado para ofrecer un sistema escalable, capaz de ejecutarse en grandes centros de procesamiento, aislando a los desarrolladores de las complejidades asociadas a la programación paralela. Está inspirado en los documentos de Google sobre MapReduce [7] y Google File System (GFS) [8], un sistema de ficheros distribuido diseñado por Goolge. Hadoop fue creado por Doug Cutting, creador de Apache Lucene, una de las librerías más utilizadas para búsqueda e indexado de textos. En concreto, Hadoop surge en 2005 como parte de Apache Nutch, un motor de búsqueda web que formaba parte del proyecto Lucene. En 2006 Doug Cutting entra a formar parte de Yahoo!, empresa que dedica un equipo completo al desarrollo de Hadoop. Es en 2008 cuando se consolida como un proyecto independiente dentro de la Fundación Apache y empieza a ser utilizado por empresas como Last.fm, Facebook o The New York Times, además de la propia Yahoo! [9]. Alrededor del proyecto Apache Hadoop han surgido numerosos nuevos proyectos formando lo que se conoce como el “Ecosistema Hadoop”. Se trata de iniciativas que aportan soluciones concretas en diversos ámbitos de aplicación, en su mayoría, desarrollados bajo el amparo de la Apache Software Fundation. No obstante, también surgen iniciativas de terceros como puede ser Cloudera Impala (que se discutirá más adelante), todos estos proyectos conforman un ecosistema muy rico y en constante crecimiento. Las primeras versiones de Hadoop estaban compuestas por dos plataformas software: Hadoop Distributed File System (HDFS) como sistema de almacenamiento y MapReduce como sistema de procesamiento. - Hadoop Distributed File System (HDFS): se trata de un sistema de archivos distribuido que permite que un fichero no se almacene en una única máquina sino que replica la información en varias máquinas consiguiendo así proporcionar alta disponibilidad y mayor rendimiento con accesos en paralelo. - MapReduce: se trata de un framework que permite al programador abstraerse de las tareas propias de la programación paralela. Es decir, permite que un programa escrito de forma convencional se pueda ejecutar en un clúster Hadoop, aprovechando los recursos aportados por todos los servidores que conforman el clúster de forma eficiente. En la actualidad, esta primera versión coexiste con una nueva versión en la que se ha incluido una arquitectura renovada mucho más flexible que permite una integración más simple con nuevos Análisis tecnológico Página 38 de 123 componentes software, incluyendo alternativas al framework de procesamiento MapReduce original. Esta flexibilidad hace que esta nueva versión, Hadoop 2.0, tenga un mayor rango de casos de uso que la versión original, pensada para el procesamiento batch de grandes cantidades de información. Además, esta nueva arquitectura permite una mejor gestión de los recursos disponible proporcionando una mejor escalabilidad con respecto al número de nodos que forman el clúster [5]. En la figura 4.1 se muestra una primera aproximación de esta profunda evolución. Figura 4.1: Hadoop 2.0 4.2.1. Hadoop Distributed File System Hadoop Distributed File System (HDFS) consiste en un sistema de archivos distribuido diseñado para dar respuesta a la necesidad de almacenar ficheros de gran tamaño utilizando hardware de propósito general, abaratando de este modo los costes del sistema. Realmente, HDFS consiste en una capa de abstracción (figura 4.2) que se sitúa sobre el sistema de archivos nativo ofreciendo, como veremos a continuación, alta disponibilidad, tolerancia a fallos y accesos eficientes a ficheros distribuidos en un clúster Hadoop. Figura 4.2: Abstracción HDFS HDFS está diseñado siguiendo una arquitectura maestro/esclavo en la que únicamente existe un maestro que se encarga de mantener el espacio de nombres del sistema de archivos y de gestionar el acceso de los clientes a los datos. Por otro lado, existen una serie de nodos esclavos, generalmente uno por cada nodo del clúster, que se encargan de almacenar los datos. Análisis tecnológico Página 39 de 123 HDFS está soportado por los siguientes demonios que ofrecen todos los servicios que lo conforman: - NameNode: se ejecuta en el nodo maestro, mantiene el espacio de nombres y el árbol que define su estructura así como todos los metadatos acerca de cada uno de los ficheros y carpetas que lo forman. Esta información se almacena en dos ficheros: fsimage y el fichero de log edits. Además, el NameNode mantiene información acerca de que DataNode contiene cada bloque, sin embargo, esta información no se mantiene en almacenamiento persistente sino que se construye cuando se inicia el sistema. Se trata de uno de los puntos que será modificado en la versión Hadoop 2.0 por tratarse de un cuello de botella por el que tiene que pasar todas las peticiones de los clientes además de tratarse de un punto único de fallo. - Secondary NameNode: a pesar de que su nombre puede sugerir lo contrario, no se trata de un NameNode de respaldo. Como ya hemos comentado, en el NameNode se mantiene un fichero fsimage en el que se almacena el estado del sistema, además, cada vez que se realiza una operación se registra en el fichero de log edits. Este último fichero puede llegar a ser demasiado grande cuando el clúster lleve mucho tiempo operativo puesto que únicamente se elimina cuando se reinicia el sistema. El papel del Secondary NameNode es realizar estas operaciones de vaciado del fichero edits de forma periódica aplicando los cabios en el fichero fsimage, se trata de un proceso que puede llegar a ser muy pesado con lo que se recomienda ejecutar este servicio en un nodo diferente al que se está ejecutando el NameNode. - DataNode: se ejecuta en los nodos esclavos del clúster, se encargan de almacenar los datos y, como veremos más adelantes, atender las peticiones de lectura/escritura de los clientes. Los ficheros se almacenan físicamente en el clúster Hadoop divididos en bloques, originalmente, cada bloque contaba con un tamaño de 64MB siendo cada vez más frecuente una configuración de 128MB. Es importante destacar que si el fichero no posee un tamaño múltiplo del tamaño de bloque, el último bloque simplemente es más pequeño, esto es de especial importancia teniendo en cuenta los tamaños de bloque que estamos manejando. Una aproximación en la que todos los bloques tienen un tamaño fijo podría suponer desperdiciar una gran cantidad de espacio de almacenamiento rellenando los últimos bloques de cada fichero con datos inservibles. Cada bloque se almacena replicado en los DataNode del clúster con el fin de proporcionar tolerancia a fallos, el factor de replicación por defecto en Hadoop es 3 y sigue el siguiente esquema: se almacena un bloque en un nodo del rack local en el que se está ejecutando la aplicación cliente que ha solicitado el almacenamiento (si la aplicación cliente no se ejecuta en el clúster se selecciona al azar), el segundo bloque replicado se almacena en un nodo perteneciente a un rack diferente al del primer nodo y, por último, se almacena la tercera copia en un nodo del mismo rack al que pertenece este segundo nodo. Esto permite reducir el tráfico entre diferentes racks asegurando un mayor rendimiento puesto que, en la mayor parte de los casos, el ancho de banda disponible entre nodos del mismo rack es mayor que entre diferentes racks. Además, se apoya en el hecho de que el fallo de un rack es mucho menos frecuente que el fallo de un nodo. El valor de replicación puede variar dependiendo de cada sistema, se trata de un compromiso claro entre rendimiento y alta disponibilidad, así en sistemas en los que tengamos algún mecanismo Hardware que proporcione resistencia a fallos como puede ser una configuración en RAID podemos reducir este factor. Como ya hemos visto, prima la localidad de los datos, esto se traduce en que cuando se ejecuta un algoritmo en el clúster es la aplicación la que se mueve a los DataNode en los que se encuentran los datos y no al revés. Análisis tecnológico Página 46 de 123 En la figura 4.8 se da una visión global del funcionamiento de esta arquitectura cuando lanzamos una nueva aplicación: Figura 4.8: Ejecución de job en YARN Los pasos a seguir son los siguientes: 1. El programa cliente envía una aplicación al clúster para su ejecución. 2. El ResourceManager reserva un contenedor en un nodo en el que ejecutará el AppliationMaster propio del tipo de aplicación que se ha enviado al clúster por parte del cliente. 3. El ApplicationMaster se registra en el ResourceManager con el fin de que el cliente pueda consultar el estado de la ejecución. 4. El ApplicationMaster negocia la utilización de recursos con el ResourceManager a través del concepto de contenedor que ya hemos comentado. 5. La aplicación se ejecuta en los contenedores reservados en el paso anterior y se comunica con el ApplicationMaster a través de un protocolo dependiente de cada aplicación con el fin de informar acerca del estado de la ejecución. 6. El programa cliente también se comunica con el ApplicationMaster a través de un protocolo dependiente de la aplicación. El cliente obtiene una referencia del ApplicationMaster a través del registro que se ha realizado en el paso 3 en el ResourceManager. Esta arquitectura soluciona alguno de los problemas presentes en Hadoop 1.0 como la mejor escalabilidad del ResourceManager frente al JobTracker, sin embargo, el ResourceManager sigue siendo un único punto de fallo. Al igual que ocurría en el caso de HDFS con el NameNode, se despliegan dos ResourceManager, uno en estado activo y otro en standby, de este modo se consigue un mayor nivel de redundancia en este punto que resulta crítico para el funcionamiento del sistema. Análisis tecnológico Página 47 de 123 4.2.3. Distribuciones Como ya hemos visto, existen diferentes versiones de Hadoop que siguen siendo utilizadas de forma simultánea. Además de estas versiones principales, existen varias ramas de desarrollo independientes. El ecosistema Hadoop está en constante crecimiento, con un gran número de proyectos que cubren una gran variedad de casos de uso, todo ello hace que desplegar y configurar correctamente un clúster Hadoop pueda llegar a ser muy complejo. Con el fin de reducir esta complejidad surgen una serie de distribuciones que integran diversos servicios en Hadoop ofreciendo un único producto testado y con garantías. Además, los proveedores de estas distribuciones pueden añadir componentes propietarios. Esto puede suponer un problema a la hora de realizar una migración del sistema a una distribución diferente con lo que la decisión inicial cobra especial relevancia. A continuación comentaremos las distribuciones de Hadoop más extendidas [10] y seleccionaremos la más adecuada para nuestro proyecto y que, posteriormente, desplegaremos en el entorno de pruebas. 4.2.3.1. Cloudera Cloudera nace en marzo de 2009 con el principal objetivo de ofrecer soporte, servicios y formación acerca de Apache Hadoop y todo su ecosistema. Su principal producto se denomina Cloudera Distribution of Hadoop (CDH) [11] que consiste en una distribución de Hadoop con licencia 100% open source. Una de sus características más destacables es la inclusión de Cloudera Manager, una herramienta gráfica que facilita las labores de instalación y mantenimiento del clúster. Las características que ofrece esta aplicación forman junto con los diferentes servicios de soporte disponibles la principal diferencia entre las versiones gratuitas y las versiones que se distribuyen bajo subscripción anual. En la siguiente figura se puede ver una visión general de la arquitectura de CDH correspondiente a la versión 5.4, la más reciente en el momento de realizar este proyecto. Figura 4.9: Arquitectura CDH Análisis tecnológico Página 48 de 123 4.2.3.2. Hortonworks Hortonworks fue fundado en 2011 por un grupo de ingenieros que pertenecían al grupo original de desarrollo de Hadoop dentro de Yahoo!. Su distribución recibe el nombre de Hortonworks Data Platform (HDP) [12], se trata de un producto totalmente gratuito pero están disponibles una serie de servicios de soporte y formación de pago. HDP incluye un sistema de gestión y administración del clúster similar a Cloudera Manager denominado Apache Ambari. A diferencia de Cloudera Manager no se trata de una herramienta propietaria aunque no ha alcanzado todavía el mismo nivel de madurez. En la figura 4.10 se muestra la arquitectura general de HDP. Figura 4.10: Arquitectura HDP 4.2.3.3. MapR MapR [13] nace en 2009 centrado en prestar servicios empresariales sobre Hadoop. Esta distribución sustituye HDFS por un sistema de archivos basado en NFS compatible con POSIX. No obstante, se ofrecen sistemas para asegurar la compatibilidad con otras versiones incluyendo HDFS. MapR también ofrece un sistema de gestión propio. Esta distribución está disponible bajo las siguientes nomenclaturas M3, M5 y M7. M5 se trata de la distribución comercial básica para empresas, M3 es la versión gratuita que carece de algunas características como alta disponibilidad. Por último, M7 consiste en un producto con características más avanzadas que incluye una versión revisada del API de HBase. Análisis tecnológico Página 49 de 123 Figura 4.11: Arquitectura MapR 4.2.4. Ecosistema Hadoop En esta sección se cubren todas las tecnologías que se han barajado a la hora de implementar nuestro sistema. En el capítulo de Diseño se pueden ver las tecnologías que finalmente se han seleccionado así como el rol que juegan dentro de la arquitectura final del sistema. 4.2.4.1. Apache Avro Apache Avro [14] consiste en un sistema de serialización basado en esquemas, estos esquemas se almacenan junto a los datos de tal forma que no es necesario almacenar una etiqueta para cada uno de los valores reduciendo el overhead asociado. De este modo se consigue un sistema más eficiente y con un menor consumo de espacio en disco con respecto a otros sistemas de serialización como el estándar de Java. Estos esquemas se almacenan en formato JSON. Para realizar las lecturas es necesario obtener primero el esquema asociado a los datos almacenados con el fin de poder interpretarlos correctamente. En nuestra implementación, utilizaremos esta herramienta para la serialización de todos los datos desde el momento en que el sistema de Dispensación Electrónica los genera hasta que son recibidos por el sistema de procesamiento. 4.2.4.2. Apache Flume Flume [15] es una herramienta distribuida, robusta y de alta disponibilidad para recolectar, agregar y mover grandes cantidades de datos de log generados por diversas fuentes. Se basa en una arquitectura simple y flexible que permite la retransmisión de datos en tiempo real incorporando mecanismos de recuperación de errores (figura 4.14). Los componentes principales dentro de Flume se denominan agentes, estos están formados por fuente, canal y sumidero. La fuente recibe eventos Análisis tecnológico Página 50 de 123 de terceros sistemas que están generando los datos que se desean retransmitir, la fuente almacena estos eventos en el canal que actúa a modo de buffer intermedio que permite desacoplar los dos extremos del agente Flume. Por último, tenemos el sumidero que se encarga de entregar los eventos que se encuentran en el canal al sistema al que queremos que lleguen los datos. En la figura 4.12, a modo de ejemplo, los datos recibidos se almacenan en HDFS. Cabe destacar que este se trata de un ejemplo sencillo, pero en realidad, un mismo agente Flume puede contar con un número arbitrario de cada uno de sus componentes, de este modo, podemos tener múltiples fuentes que almacenan datos en uno o varios canales y que son consumidos por uno o varios sumideros. Figura 4.12: Agente Flume Existen una gran variedad de tipos de fuentes, canales y sumideros, además de la posibilidad de crear nuevos tipos ad hoc. Uno de los tipos que resulta especialmente útil consiste en las fuentes y los sumideros que utilizan Avro. Estos serializan los datos que se retransmiten a través de esta herramienta. La utilización de Avro facilita la creación de arquitecturas multicapa de agentes Flume tal y como se muestra en la figura 4.13: Figura 4.13: Arquitectura Flume multicapa De este modo, se consigue consolidar en un único flujo de datos los eventos producidos por diversas fuentes y enviados a través de diferentes agentes Flume. Podemos pensar en un escenario en el que cada uno de los agentes se ejecuta en un nodo independiente. Un fallo en el nodo que alberga el algente Agent1, no supone ningún problema para ninguno de los demás agentes por lo que Análisis tecnológico Página 51 de 123 los otros dos sistemas que están generando eventos podrán seguir retransmitiéndolos. A pesar de esto, tenemos un único punto de fallo en agente Agent4, puesto que si este agente falla por cualquier motivo se corta la comunicación con HDFS (en este caso los eventos se almacenan deserializados en HDFS). En todo caso, esto puede no suponer un problema ya que los nuevos datos generados se almacenan en los canales de los nodos de la primera capa hasta que el otro agente Flume se recupere. En algunos sistemas puede no ser aceptable que se interrumpa la comunicación a pesar de que no haya pérdida de datos. En estos casos necesitaríamos una segunda capa con mayor redundancia de agentes Flume o incluso un mayor número de capas en arquitecturas muy complejas en las que los datos provienen de múltiples sistemas totalmente heterogéneos en las que es necesario realizar una consolidación parcial en una capa intermedia. En lo que se refiere a los canales, existen dos tipos fundamentales, en memoria y como un archivo [16]. Los canales que almacenan los datos en memoria cuentan con unos tiempos de acceso más reducidos otorgando mayor rendimiento al sistema, sin embargo, si se produce algún fallo en el nodo que alberga el agente Flume los datos se pierden. Además, este tipo de canales tienen una capacidad más reducida que un canal basado en un fichero en el que los eventos se almacenan en el sistema de ficheros del nodo. Cabe destacar que existen otros tipos de canales más complejos como los que se construyen sobre un clúster Kafka, tal y como se describe en el siguiente apartado, o la utilización de un conector JDBC para almacenar los eventos en una base de datos. Utilizaremos Flume para retransmitir los eventos desde los nodos del sistema de Dispensación Electrónica a los nodos del clúster Hadoop. Hemos barajado Kafka como alternativa a la hora de implementar esta parte del sistema pero, como veremos en el siguiente apartado, Flume se adapta mejor a los requisitos que definen nuestro sistema. 4.2.4.3. Apache Kafka Apache Kafka [17] consiste en una herramienta distribuida y con redundancia que ofrece las funcionalidades de un sistema de envío de mensajes. En la figura 4.14 se puede ver una visión de alto nivel de la arquitectura del sistema, Kafka mantiene los mensajes organizados en categorías denominadas topics, existen una serie de productores que publican los mensajes en el clúster Kafka, y por otro lado, también existen una serie de procesos que se suscriben a los topics y que se denominan consumidores. Figura 4.14: Arquitectura Kafka Como ya hemos comentado, un topic consiste en una categoría bajo la que se agrupan los mensajes, cada uno de los topic se encuentra particionado dentro de clúster Kafaka tal y como se muestra en la figura 4.15. Análisis tecnológico Página 52 de 123 Figura 4.15: Topic de Kafka Cada partición consiste en una secuencia ordenada de mensajes a la que se están continuamente añadiendo nuevos mensajes. Cada uno de los mensajes tiene asignado un id secuencial que lo identifica dentro de la partición. Kafka mantiene todos los mensajes que han sido publicados, hayan sido consumidos o no, durante un periodo de tiempo específico que se puede configurar, después de este periodo los mensajes se descartan para liberar espacio. Cada consumidor mantiene la posición del último mensaje consumido, llamado “offset”. Habitualmente, esta posición se incrementa de forma lineal de tal forma que los mensajes se consumen por orden, no obstante, dado que la posición la controla el consumidor puede leer los mensajes en un orden arbitrario. El uso de particiones permite escalar el tamaño de cada uno de los topics dividiendo los datos en múltiples nodos de forma redundante con el fin de conseguir tolerancia a fallos. Existe un nodo “líder” y un conjunto de nodos “seguidores”. El nodo líder maneja las peticiones de lectura y escritura mientras que los seguidores mantienen una copia del líder de forma automática. Todos los nodos actúan como líder para alguna de las particiones mientras que actúan como seguidores para otras. Los consumidores pueden formar grupos de tal forma que cada uno de los mensajes de un topic únicamente se entrega a uno de los clientes de cada grupo. En la figura 4.16 podemos ver un topic que cuenta con cuatro particiones alojadas en los servidores Server 1 y Server 2, además, tenemos dos grupos de consumidores. Podemos ver como en esta configuración es posibles entregar mensajes de forma simultánea y en paralelo a cada uno de los consumidores. Figura 4.16: Grupos de consumidores Análisis tecnológico Página 53 de 123 Como podemos ver, Kafka sería una alternativa válida a la hora de implementar la retransmisión de los datos convirtiéndose en una alternativa a Flume. Una de las principales ventajas de este sistema es la gran escalabilidad que presenta con respecto al número de productores y consumidores. En nuestro caso, tendremos un único consumidor que será nuestro sistema de procesamiento y ocho productores puesto que, como veremos en una sección posterior, el sistema de Dispensación Electrónica se encuentra formado por ocho procesos diferentes. No necesitaremos un sistema que ofrezca una gran escalabilidad en este sentido dado que tanto el número de consumidores como de productores se mantiene reducido y constante. Por otro lado, Flume nos permite configurar una arquitectura multicapa cuya primera capa se desplegará en los nodos del sistema de Dispensación Electrónica. Esta primera capa seguirá funcionando y almacenando eventos en los respectivos canales ante un fallo del clúster, lo que nos permitirá cumplir con el requisito RCA_002 que establece que ante esta situación de fallo no se deben perder datos. La posibilidad de dividir los datos en diferentes flujos (topic) que nos ofrece Kafka tampoco es aplicable a nuestro caso puesto que trataremos todas las líneas de log como un único flujo de datos. Todas estas circunstancias han hecho que nos decantemos por Flume a la hora de implementar esta funcionalidad. 4.2.4.1. Apache ZooKeeper Zookeeper [18] es un sistema de coordinación de aplicaciones distribuidas que ofrece un conjunto simple de primitivas de alto nivel que permiten a las aplicaciones acceder a servicios de sincronización, configuración, mantenimiento y grupos de nombres. Permite a los procesos distribuidos coordinarse a través de un espacio de nombres jerárquico organizado de manera similar a un sistema de archivos. Esta estructura de datos se mantiene en memoria con el fin de ofrecer alto rendimiento. Cada uno de los nodos se denomina znode y juegan un papel similar al de los directorios y los archivos en un sistema de archivos tradicional (figura 4.17). Figura 4.17: Espacio de nombres A diferencia de los sistemas de archivos tradicionales, los znode mantienen un conjunto de datos asociados que pueden ser consultados y modificados por parte de las aplicaciones de forma atómica. Además, ZooKeeper ofrece alta disponibilidad por medio de una arquitectura redundante que replica los datos a través de los nodos del clúster. Estos nodos mantienen la estructura en memoria además de una imagen de backup almacenada en disco junto a un conjunto de ficheros de log en los que se guardan las transiciones que convierten la imagen de backup al estado actual del sistema. Los clientes se conectan a un único nodo del clúster ZooKeeper, en caso de fallo en la conexión se reintenta con otro nodo diferente (figura 4.18). Análisis tecnológico Página 54 de 123 Figura 4.18: Clúster ZooKeeper Necesitaremos contar con ZooKeeper instalado en el clúster puesto que, como veremos, HBase utiliza este servicio para la coordinación de los diferentes componentes en una arquitectura distribuida. En la implementación final utilizaremos HBase como sistema de almacenamiento con lo que tendremos que comunicarnos con este sistema a través de ZooKeeper desde nuestra aplicación de procesamiento de log. 4.2.4.2. Apache Hbase HBase [19] es una base de datos distribuida y orientada a columnas que se ejecuta sobre HDFS y que es capaz de soportar lecturas y escrituras aleatorias en tiempo real sobre grandes conjuntos de datos. HBase se ha implementado siguiendo las publicaciones de Google: “BigTable: A Distributed Storage System for Structured Data” [20]. Apache Hbase se ha diseñado para ofrecer escalabilidad lineal con respecto al número de nodos del clúster. No se trata de una base de datos relacional y no soporta consultas SQL sino que ofrece un API propia de acceso a datos además de un Shell a través del cual se pueden realizar consultas con un lenguaje propio. Los datos se almacenan en tablas, estas tablas están organizadas en filas y columnas. Cada una de las intersecciones entre las filas y las columnas se denomina celdas y se encuentran versionadas. Por defecto estas versiones se realizan en base a la fecha de inserción. En cada una de las celdas se mantiene un array de bytes que no se interpreta como un tipo de datos determinado. Cada fila cuenta con una clave que también se almacena como un conjunto de bytes con lo que, de forma teórica, se puede utilizar cualquier estructura de datos como clave, todas las filas de la tabla se encuentran ordenadas por su clave. Por otro lado, las columnas se encuentran organizadas formando column families, las familias en las que se agrupan las columnas se deben especificar en el momento de creación de la tabla, sin embargo, los miembros de cada familia pueden ser creados bajo demanda en cada una de las inserciones. En la figura 4.19 se puede ver un esquema en el que se muestra la estructura lógica de las tablas de HBase [21]. Análisis tecnológico Página 55 de 123 Figura 4.19: Formato de tablas en HBase Las tablas se dividen en particiones a medida que se añaden nuevas filas, estas particiones se encuentran distribuidas entre los nodos del clúster. HBase se ha diseñado siguiendo una arquitectura maestro esclavo formada por uno o más regionservers, que mantienen las regiones que forman las tablas y atienden las peticiones de los clientes, y un master, que se encarga de repartir las regiones entre los regionservers y de realizar la gestión de los posibles fallos. HBase utiliza ZooKeeper para la implementación de esta arquitectura distribuida. Por último, HBase utiliza el API de acceso a datos de Hadoop para hacer los datos persistentes, con lo que el sistema de archivos más utilizado es HDFS ofreciendo alta disponibilidad y resistencia a fallos. Surgen diversas consideraciones a la hora de diseñar una tabla en HBase. Una de las más importantes radica en el la elección de la clave puesto que determina la forma en que se ordenarán los registros y, por lo tanto, lo cerca que una fila está de otra [22]. Las filas cercanas pertenecerán a un mismo regionserver mientras que filas muy separadas pueden estar en nodos diferentes del clúster. Esto determina, por ejemplo, el número de consultas que se pueden atender en paralelo. Otro factor a tener en cuenta es el nombre de las columnas puesto que por cada celda se almacena la columna a la que pertenece así como la fecha de inserción, por lo tanto, se prefieren nombres cortos. Por último, también es importante prestar atención a como se almacenan los datos, como ya hemos comentado en HBase los datos se almacenan como secuencias de bytes sin ningún tipo asociado. Así, por ejemplo, una fecha se puede representar en un lenguaje como Java de al menos dos formas, como una cadena de caracteres o como un número que representa la fecha en milisegundos, sin embargo la segunda ocupa menos bytes que la primera (el tamaño de la cadena de caracteres depende del formato con el que se represente pero, en general, es muy superior al de un entero). De este modo al introducir una fecha en HBase es preferible no introducir la cadena de caracteres convertida directamente a bytes. Como veremos en la descripción de la arquitectura final del sistema de procesamiento de log, utilizaremos HBase como sistema de almacenamiento. La principal característica que nos ha llevado a seleccionar esta herramienta ha sido el alto rendimiento que ofrece, tanto en lecturas como en escrituras aleatorias. 4.2.4.1. Apache Hive Apache Hive [23] es una infraestructura de almacenamiento de datos construida sobre Hadoop que facilita la consulta y gestión de grandes conjuntos de datos que residen en almacenamiento distribuido. Incluye un lenguaje de consulta similar a SQL denominado HiveQL Análisis tecnológico Página 62 de 123 Figura 4.23: Topology Storm Storm se encarga de distribuir los datos de los streams de entrada de tal forma que se consiga el mayor grado de paralelismo a la hora de ejecutar la topology en el clúster. 4.2.4.6. Pentaho Reporting Se trata de una herramienta gratuita que forma parte de la edición community de Pentaho BI Suite, un conjunto de utilidades dedicadas al mundo del Business Intelligent. Pentaho Reporting [31] está compuesto por tres elementos principales: - Report Designer: se trata de una herramienta gráfica que nos permite crear definiciones de informes realizados de forma totalmente personalizada por el usuario con posibilidad de acceso a una gran variedad de fuentes de datos. - Reporting Engine: se trata del núcleo del sistema, es la parte encarga de ejecutar las definiciones creadas con la herramienta anterior y crear los informes a partir de los datos correspondientes. - Reporting SDK: nos permite embeber los informes en nuestras aplicaciones, de este modo podemos cargar una definición hecha desde la herramienta Report Designer e incluir el informe generado en la vista de nuestra aplicación. Utilizaremos este flujo de trabajo para la creación y publicación de informes en nuestra aplicación web. Además de crear la definición de lo informes que estarán disponibles en la aplicación web, proporcionaremos un mecanismo de generación de informes personalizados cumpliendo con el requisito RAP_003. 4.3. Sistema de Dispensación Electrónica Nuestro proyecto se enfoca en el desarrollo de una herramienta que pueda analizar los log de actividad de un Sistema de Receta Electrónica en tiempo real, en concreto, nos centramos en el sistema de Dispensación Electrónica (DISEL) que se encuentra actualmente implantado en Galicia. Por lo tanto, entender el funcionamiento de este sistema es clave a la hora de poder desarrollar nuestro proyecto. Análisis tecnológico Página 63 de 123 4.3.1. Arquitectura El sistema de Dispensación Electrónica está desplegado en cuatro nodos, en cada uno de estos nodos se ejecutan dos instancias, cada una en un servidor de aplicaciones diferente. De este modo tendremos cuatro nodos (ocho procesos) enviando datos de forma simultánea a nuestro clúster para ser analizados, esto condicionará el diseño de nuestro sistema de recepción de datos tal y como veremos más adelante. En todo caso, los datos se verán por parte del analizador como un único conjunto sin entrar a valorar de que nodo provienen o de que proceso dentro de ese nodo. 4.3.2. Formato de los logs En general, por cada operación se generan tres líneas de log, una en el momento en el que se recibe la petición, otra con datos que puedan ser relevantes acerca de la operación y otra en el momento en el que se emite la respuesta. Cabe destacar que, dado que se atienden múltiples peticiones de forma simultánea, estas tres líneas asociadas a una operación no tienen por qué generarse de forma consecutiva sino que se pueden intercalar con otras líneas asociadas a otras operaciones. Por lo tanto, con el fin de permitir identificar a que operación hace referencia cada una de las líneas se incorpora un identificador único por cada operación como uno de los campos que aparece en todas las líneas, independientemente del tipo que sea. A continuación definiremos el patrón que sigue cada uno de los tipos de líneas de log generados, las palabras que aparecen en cursiva se refieren a cadenas que aparecen directamente en las líneas de log originales mientras las demás se utilizan simplemente para poder hacer referencia al campo en las descripciones. 4.3.2.1. Peticiones Fecha | Nivel | plataforma | id | Petición | Servicio: servicio | Operación: operación | Cliente: cliente - Fecha: contiene la fecha de generación de la línea por parte del sistema de Dispensación Electrónica en el formato “AAAA-MM-dd HH:mm:ss,SSS”, por ejemplo: “2015-04-29 22:05:09,214”. - Nivel: el nivel de prioridad con el que se genera la línea y que, para los tres tipos de línea que estamos manejando se utiliza INFO. En los datos que manejamos para la realización de este Trabajo Fin de Grado no contamos con líneas con un nivel diferente como puede ser un error. - plataforma: este campo con el valor “plataforma” indica que se trata de peticiones recibidas por el Sistema de Dispensación Electrónica. También puede tener el valor “recursos” en aquellas líneas que se registran como consecuencia de una petición realizada por el Sistema de Dispensación Electrónica a otros sistemas. En los datos que manejamos en este Trabajo Fin de Grado únicamente manejamos líneas con el valor “plataforma”. - Id: como ya hemos comentado necesitamos un identificador único para cada operación para poder agrupar todas las líneas que hacen referencia a dicha operación. - Petición: este campo tiene siempre la cadena de caracteres “Petición” y nos permite identificar que la línea se ha generado porque se ha recibido una petición. Análisis tecnológico Página 64 de 123 - Servicio: servicio: este campo recoge información acerca del servicio que está atendiendo la petición dentro del sistema de Dispensación Electrónica. Un posible valor para este campo es: “Servicio: ServicioDispensaciones” - Operación: operación: permite identificar el tipo de operación que se está ejecutando, este campo se relaciona en cierto modo con el anterior puesto que cada servicio atiende un determinado conjunto de tipos de operación. Un posible valor sería: “Operación: registroDispensacion_eReceita”. - Cliente: cliente: este campo nos permite identificar el sistema que está realizando la petición puesto que el sistema de Dispensación Electrónica se interconecta con múltiples sistema en una arquitectura de nivel superior compleja y que no discutiremos en este documento puesto que se sale de los intereses de nuestro proyecto. Un posible valor sería: “Cliente: NCD”. 4.3.2.2. Datos Fecha | Nivel | plataforma | id | <datos><farmacia> </farmacia><farmaceutico> </farmaceutico><tipodocumento>CIP</tipodocumento><documento> </documento><fuente> </fuente></datos> Los cuatro primeros campos contienen la misma información que el caso anterior. En este tipo de línea, a estos primeros campos comunes, se le añade un campo que contiene información extra acerca de los datos asociados a la operación en formato XML. Cabe destacar que no todos los campos de este XML tienen porque tener datos para todas las operaciones sino que pueden aparecer campos vacíos. - farmacia: identificador de la farmacia que origina la ejecución de la operación. - farmacéutico: identificador del profesional que ejecuta la operación. - tipoDocumento: tipo de documento por el que se identifica al paciente y cuyo valor se recoge en el campo documento. - documento: identificador del paciente, en el formato adecuado para el documento especificado en el campo anterior. - fuente: el origen del que se han obtenido los datos de identificación del paciente (por ejemplo, a través de la banda magnética de la tarjeta sanitaria o de forma manual). 4.3.2.3. Respuestas Fecha | Nivel | plataforma | id | Respuesta | Servicio: servicio | Operación: operación | Cliente: cliente | Tamaño | Tiempo La información recogida en este tipo de línea es idéntica a la recogida en las líneas de petición a excepción de los dos últimos campos y del quinto campo que recoge el literal Respuesta. - Tamaño: este campo recoge el tamaño de la respuesta que se ha generado en bytes. - Tiempo: indica el tiempo que se ha tardado en realizar la operación. Es habitual que únicamente aparezcan las líneas de petición y respuesta y que no se incluya la línea de datos. A continuación podemos ver un ejemplo de una operación que incluye las tres: Análisis tecnológico Página 65 de 123 2015-04-29 22:05:09,214 | INFO | plataforma | [18c82e855a11c46e7d71b425f6abeab84c753bf7] | Petición | Servicio: ServicioDispensaciones | Operación: registroDispensacion_eReceita | Cliente: NCD 2015-04-29 22:05:10,792 | INFO | plataforma | [18c82e855a11c46e7d71b425f6abeab84c753bf7] | <datos><farmacia>FC00000</farmacia><farmaceutico>FT00000</farmaceutico><tipodocumento>C IP</tipodocumento><documento>DOC00000</documento><fuente>MANUAL</fuente></datos> 2015-04-29 22:05:21,072 | INFO | plataforma | [18c82e855a11c46e7d71b425f6abeab84c753bf7] | Respuesta | Servicio: ServicioDispensaciones | Operación: registroDispensacion_eReceita | Cliente: NCD | 5253 | 11859 Para estimar el volumen de datos, hemos analizado los logs de Dispensación Electrónica de un día y nos encontramos con 501.649 líneas con datos, 731.845 líneas asociadas a Peticiones y 716.899 líneas asociadas a Respuestas lo que supone un total de 1.950.393. Podemos asumir un volumen total cercano a los 2.000.000 líneas/día, únicamente para estos tres tipos de líneas que son las únicas que manejaremos en este Trabajo Fin de Grado. Si nos centramos en los datos, para el mismo día, obtenemos un total de 125.547 documentos de paciente diferentes, 2.897 farmacéuticos diferentes y 1.337 farmacias diferentes. Estos datos pueden dar una idea de la magnitud de los ficheros de log generados y de la necesidad de una herramienta que permita automatizar, en la medida de lo posible, el análisis de estos datos ante la imposibilidad de abarcarlos por completo de forma manual. 4.4. Virtualización En lo que se refiere a la tecnología de virtualización no se ha llevado a cabo una selección tecnológica como tal puesto que en el requisito RAP_004 se establece como sistema de virtualización Docker con el fin de explorar las ventajas y desventajas que puede ofrecer. A continuación realizaremos una descripción detallada de esta tecnología. 4.4.1. Docker Docker [32] ofrece un sistema de virtualización basado en contenedores que utiliza una serie de herramientas propias del kernel de Linux para crear entornos de ejecución independientes con un overhead muy reducido en comparación con otros sistemas de virtualización. La idea que está detrás de la mayor parte de las tecnologías de virtualización consiste en crear una capa de abstracción sobre la que se ejecuta una nueva máquina de forma aislada. Por el contrario, los contenedores consisten en crear entornos de ejecución aislados sobre el mismo sistema operativo, no se virtualiza una máquina completa. En la figura 4.24 se puede ver esto gráficamente: Análisis tecnológico Página 66 de 123 Figura 4.24: Contenedores frente a máquinas virtuales Como se puede apreciar los contenedores comparten todos aquellos recursos que son comunes incluyendo el kernel del sistema operativo y las dependencias de las aplicaciones que se ejecutan en ellos. En el caso de las máquinas virtuales tradicionales, se opta por crear un nuevo sistema operativo que se ejecuta sobre la capa de virtualización y en el que se instalan todas las dependencias necesarias. Esto convierte a los contenedores en una alternativa más eficiente en lo que al uso de recursos se refiere. No obstante, los contenedores se convierten en una opción menos flexible puesto que el sistema que se ejecuta dentro de cada uno de ellos debe ser el mismo, o del mismo tipo, que el sistema anfitrión. De este modo podemos ejecutar una distribución Linux dentro de un contenedor que se despliega sobre una máquina Linux, pero no podemos ejecutarlo, por ejemplo, sobre un sistema Windows. Como ya hemos comentado Docker utiliza una serie de características del kernel de Linux que le permiten crear contendores aislados, cada uno de los cuales cuenta con su propio entorno de red, gestor de recursos y almacenamiento. Esto permite la ejecución de múltiples contenedores en un mismo equipo sin que puedan llegar a interferir entre ellos. Cabe destacar que Docker también está disponible para otros sistemas además de Linux tales como Windows o OS X. En estos casos, los contenedores se despliegan dentro de una máquina virtual ligera que ofrece todas las funcionalidades necesarias del kernel de Linux. Esta aproximación es más ineficiente puesto que supone la inclusión de una nueva capa de virtualización que es justo lo que queremos evitar con el uso de contenedores. En todo caso, únicamente se crea una máquina virtual en cada host sobre la que se ejecutan todos los contenedores. Además se incluye un cliente que permite manejar estos contenedores desde la línea de comandos del sistema anfitrión de forma transparente tal y como se muestra en la figura 4.25. Análisis tecnológico Página 67 de 123 Figura 4.25: Docker en Windows En sistemas Linux no es necesaria la presencia de esta máquina virtual, pero también se sigue una arquitectura cliente servidor en la que el cliente habitualmente se instala en el mismo host que el demonio encargado de gestionar los contenedores, no obstante, se puede instalar el cliente en un host remoto. Existen tres conceptos fundamentales dentro de Docker, las imágenes, los registros y los contenedores [33]. 4.4.1.1. Imágenes Se trata de los elementos a partir de los que se crean los contenedores. Consisten en ficheros de definición en los que se especifican las acciones que se deben llevar a cabo para realizar la configuración base a todos los contenedores. Entre estas acciones se encuentran añadir ficheros, ejecutar un comando, abrir puertos o definir variables de entorno. Además, se permite definir una imagen partiendo de otra ya existente. De este modo para la creación de la imagen resultante se ejecutarán todas las acciones de las imágenes que forman la cadena. A continuación se puede ver un ejemplo sencillo: FROM fedora RUN yum install -y gcc ADD ./myprogramfiles.tar /tmp Código 4.1 En este caso se crea una imagen a partir de la imagen denominada “fedora”. La palabra clave RUN indica que se debe ejecutar un comando, en este caso se instala gcc. Por último se añade una archivo, que se encuentra en el directorio en el que se encuentra el fichero de definición y que en los contenedores que se creen a partir de esta imagen se encontrará en “/tmp”. Una vez se crea la imagen a partir de estos ficheros, se mantiene almacenada en cache de tal forma que cuando se inicia un contenedor se coge dicha imagen como la configuración base. Análisis tecnológico Página 68 de 123 4.4.1.2. Registros Las imágenes creadas se organizan en registros que pueden ser públicos o privados. La comunidad de Docker mantiene un registro público denominado Docker Hub en el que están disponibles un gran número de imágenes que se puede utilizar como base para nuevas imágenes o pueden ser utilizadas directamente para crear nuevos contenedores. 4.4.1.3. Contenedores Se trata del elemento central, representa un espacio de ejecución independiente en el que se pueden instalar las aplicaciones o servicios que deseamos ejecutar de forma aislada. En cada uno de estos contenedores ejecutaremos uno de los nodos del clúster Hadoop. Además de los nodos del clúster, también crearemos contenedores para desplegar tanto la aplicación que simula el funcionamiento del sistema de Dispensación Electrónica como la aplicación web de generación informes. Los entornos de ejecución además de estar aislados entre sí también están totalmente aislados del sistema anfitrión. Además, el contenido de estos contenedores no condiciona de ninguna manera el funcionamiento de Docker. Diseño Página 69 de 123 5. Disen o En este capítulo describiremos la arquitectura general del sistema, pasando a continuación a proponer un diseño más concreto acerca del sistema de procesamiento en tiempo real. En este apartado indicaremos las herramientas seleccionadas para la implementación del sistema final. Por último, introduciremos el diseño de la aplicación Web que pone los informes a disposición de los usuarios y de la aplicación que simula el funcionamiento del sistema de Dispensación Electrónica a partir de los ficheros de log de los que disponemos. 5.1. Arquitectura general del sistema A continuación describiremos la arquitectura general del sistema en la que se puede ver cómo interactúan los diferentes componentes a un alto nivel de detalle. En la figura 5.1 vemos como la comunicación entre el sistema de Dispensación Electrónica y el sistema de procesamiento de log se realiza a través de log4j tal y como se especifica en el requisito RAP_001. El sistema de procesamiento de log consistirá en un clúster Hadoop (requisito RAP_002). Describiremos este sistema en detalle más adelante. El requisito RDI_001 establece que se debe implementar una aplicación web que contenga una serie de informes predefinidos, esta aplicación obtendrá los datos del clúster Hadoop a través de una conexión JDBC. Por último implementaremos un sistema de monitorización del sistema de procesamiento en tiempo real que nos permita cumplir con lo establecido en los requisitos RDI_007 y RDI_008 que indican que se deben generar informes acerca del estado del sistema con el fin de validar su correcto funcionamiento a los efectos de la fase de pruebas del proyecto. Este sistema de monitorización realizará peticiones HTTP tal y como comentaremos en una sección posterior dedicada exclusivamente a este componente. Figura 5.1: Arquitectura general del sistema 5.2. Arquitectura del sistema de procesamiento de log En esta sección presentaremos la arquitectura general del sistema de procesamiento de log. En primer lugar, discutiremos la arquitectura lambda [34], un modelo de desarrollo de aplicaciones Big Data que combina procesamiento en tiempo real [35] con procesamiento batch para ofrecer un sistema robusto y de baja latencia. La arquitectura Lambda ofrece una solución muy general con aplicación potencial en un gran número de escenarios. Propondremos una solución alternativa, mucho más específica, pensando en las características que definen nuestro sistema. 5.2.1. Arquitectura Lambda La arquitectura Lambda fue diseñada por Nathan Marz, un experimentado desarrollador de aplicaciones Big Data con experiencia en empresas como Backtype o Twitter. Se trata de una solución Diseño Página 70 de 123 de propósito general, con aplicación en una gran variedad de escenarios ofreciendo una solución robusta, escalable y de baja latencia. Esta arquitectura se utiliza para implementar sistemas en los que necesitamos aplicar una serie de funciones sobre un gran conjunto de datos en tiempo real. Idealmente, podríamos modelar el problema con una aproximación del tipo: consulta = función(todos los datos). En la práctica, esto es inabordable por la potencia de cómputo necesaria para poder procesar enormes cantidades de datos en cada consulta. Nathan Marz propone mantener una serie de vistas en las que se mantienen los resultados preprocesados, de este modo, las consultas se pueden realizar directamente sobre estas vistas eliminando la necesidad de realizar todo el procesamiento en cada consulta. Para lograr esto, se divide el sistema en tres capas: capa de procesamiento batch, capa de velocidad y la capa de servicio. 5.2.1.1. Capa de procesamiento batch Esta capa se encarga de mantener el conjunto de datos maestro, una estructura en la que se mantienen todos los datos inmutables y a la que únicamente se añaden nuevos registros. Además, en esta capa, se procesan todos estos datos de forma periódica con el fin de ofrecer un conjunto de vistas que contenga los resultados preprocesados. Es importante tener acceso a la totalidad de los datos originales para poder generar cualquier vista arbitraria. De este modo, se consigue un sistema extensible en el que añadir una nueva vista no supone más que añadir la nueva funcionalidad al sistema de procesamiento, obteniéndose en la siguiente ejecución una nueva vista con los nuevos resultados. Figura 5.2: Capa de procesamiento batch 5.2.1.2. Capa de servicio Se encarga de indexar las vistas producidas por la capa de procesamiento batch. Básicamente, consiste en una base de datos sobre la que los clientes pueden realizar consultas y obtener los resultados preprocesados de forma eficiente. La frecuencia con la que se actualizan las vistas de la capa de servicio depende de la frecuencia con la que la capa batch procesa los datos originales. Estos periodos de actualización suelen ser de varias horas o incluso días dependiendo de cada caso. No es Diseño Página 71 de 123 necesaria una base de datos que ofrezca una latencia reducida en escrituras aleatorias lo que puede simplificar el funcionamiento del sistema y su implementación. Un ejemplo de implementación para esta capa pueden ser tablas externas en Hive que hacen referencia a los ficheros que contienen los datos procesados que ha producido la capa batch. En esta capa se simplifica el acceso a los datos por parte de los clientes y se consigue aislarlos de la implementación de la capa batch. 5.2.1.3. Capa de velocidad Con las dos capas anteriores, tenemos un sistema en el que los resultados no están disponibles hasta que termina la siguiente ejecución. Dado que este periodo suele ser de varias horas, los resultados no tienen en cuenta los datos más recientes. En esta capa se producen las vistas con los resultados relativos a los últimos datos recibidos, que no se han tenido en cuenta en la capa de procesamiento batch. La principal diferencia entre esta capa y la capa de procesamiento batch radica en que, en este caso, las vistas se actualizan a medida que se reciben nuevos datos, mientras que en el caso de procesamiento batch, los resultados se obtienen tras procesar el total de los datos. Esto supone que, en este caso, necesitamos un medio de almacenamiento que ofrezca baja latencia, tanto en escrituras, como en lecturas aleatorias, ya que se están realizando continuas actualizaciones sobre los resultados finales. Por último, necesitamos un componente capaz de agregar los resultados obtenidos de las vistas producidas en tiempo real y de las vistas producidas en batch (figura 5.3). Figura 5.3: Capa de velocidad En la figura 5.4 se puede ver un diagrama en el que se muestran los diferentes componentes que dan lugar a un sistema implementado siguiendo las directrices de la arquitectura Lambda. Diseño Página 78 de 123 En todo caso, este modelo de capa de almacenamiento únicamente es válido cuando tenemos datos estructurados que podemos almacenar directamente en nuestra base de datos sin necesidad de un procesamiento previo. Si es necesario realizar un procesamiento complejo sobre los datos originales para poder extraer información estructurada podríamos estar perdiendo parte de los datos originales. Para la implementación de esta capa hemos seleccionado Hive, dado que se trata de un estándar de facto en lo que se refiere a almacenamiento estructurado en el ecosistema Hadoop. La mayor parte de las herramientas de reporting son totalmente compatibles con este sistema de almacenamiento. Además, se trata de un sistema que proporciona drivers JDBC/ODBC con lo que las posibilidades que tenemos para implementar los clientes son muy amplias. 5.2.2.3. Capa de procesamiento En esta capa se realiza el procesamiento en tiempo real de todos los datos utilizando únicamente Spark Streaming. Necesitamos un sistema eficiente para el acceso a datos que permita cumplir las restricciones temporales impuestas por un sistema de procesamiento en tiempo real. Dado que Hive se ejecuta sobre MapReduce, no se adecua a nuestro sistema por lo que utilizaremos Spark SQL para acceder directamente a los metadatos de Hive. De este modo, obtenemos un sistema de almacenamiento totalmente estándar desde el punto de vista de los clientes y un sistema de baja latencia desde el punto de vista de la capa de procesamiento. En esta capa se procesan los datos procedentes de la capa de recolección y se actualizan los resultados preprocesados disponibles en la capa de almacenamiento. Además, se clasifican las líneas de log en peticiones, respuestas y líneas que contienen datos acerca de las operaciones y se insertan en la tabla correspondiente, se trata del único procesamiento que recibe el conjunto de datos maestro. Este procesamiento es necesario ya que tenemos un conjunto de datos heterogéneo con lo que no es posible almacenarlos en un única tabla. En todo caso, se trata de un procesamiento muy simple que no supondrá pérdida de información. Como se puede ver en la descripción general del sistema que hemos mostrado anteriormente, hemos incluido un módulo que hace referencia al reprocesado. Como ya mencionamos en la definición de la arquitectura Lambda, el reprocesado se debe tener en cuenta siempre que se realice un cambio en la lógica de procesamiento de los datos. En nuestro caso, únicamente ejecutaremos un programa Spark, cada vez que despleguemos un nuevo sistema de procesamiento Spark Streaming, que recalculará todos los resultados a partir de los datos originales presentes en la capa de almacenamiento. Como veremos en la sección de implementación, ejecutar un código Spark Streaming como un programa batch no supone grandes modificaciones, únicamente deberemos leer los datos desde la capa de almacenamiento en lugar de desde la capa de recolección. 5.2.2.4. Problemas encontrados y versión final A la hora de poner en práctica esta arquitectura nos hemos encontrado con algunos problemas que han obligado a evolucionar nuestro diseño a una nueva versión en la que se modifica alguna tecnología y se añade algún componente extra. Como ya hemos comentado, el acceso a datos desde la capa de procesamiento se hacía a través de Spark SQL, en la versión de Spark que manejamos, la 1.2.1, no es posible realizar actualizaciones sobre una base de datos. Esto es una consecuencia directa del concepto de RDD que Diseño Página 79 de 123 ya hemos descrito. Se entiende un RDD como un conjunto de datos inmutable a partir del cual se puede obtener un nuevo RDD realizando alguna transformación. Spark SQL maneja una abstracción similar al concepto de RDD llamado Schema RDD y que, por lo tanto, se trata de conjuntos de datos inmutables con lo que únicamente permite añadir nuevos registros a la base de datos. Esta aproximación sería válida, por ejemplo, como método de acceso a datos para la capa de procesamiento batch de la arquitectura Lambda original ya que, como vimos en su descripción, vuelve a generar todos los resultados a partir del conjunto de datos maestro y no de forma incremental a partir de lo que ya tenemos computado en la base de datos. La utilización de Hive directamente no era viable debido a las restricciones de rendimiento que impone un sistema de procesamiento en tiempo real. Por lo tanto, hemos decidido utilizar HBase como sistema de almacenamiento dado que ofrece un gran rendimiento en lecturas y escrituras aleatorias. Esto tiene consecuencias directas, tanto para los programas cliente que generan informes, como para los usuarios que acceden directamente a la base de datos y es que HBase no es una base de datos SQL. Con el fin de ofrecer una interfaz SQL introduciremos un nuevo componente en la capa de almacenamiento. Crearemos una serie de vistas en Apache Phoenix sobre los datos presentes en HBase de tal forma que los clientes ejecutarán sus consultas a través de este nuevo componente y no directamente sobre la base de datos. A continuación se puede ver un esquema de la arquitectura final: Figura 5.12: Arquitectura alternativa final Conseguimos de este modo todas las ventajas que nos proporciona el lenguaje SQL a la hora de realizar análisis sobre los datos y de obtener interoperabilidad con herramientas de consulta y generación de informes y, además, tenemos un mecanismo de acceso a datos eficiente desde el punto de vista de la capa de procesamiento. Como hemos visto en esta nueva versión la capa de almacenamiento se ha rediseñado completamente. Contaremos con dos tablas en HBase, una dedicada a almacenar el conjunto completo de datos (todas las líneas de log que se reciben) y otra dedicada a mantener los resultados preprocesados. Diseño Página 80 de 123 La primera de las tablas la llamaremos “log” y contará con una única column family que llamaremos “campos”, las columnas que la forman dependerán del tipo de línea que se esté almacenando. Se contemplan cuatro tipos de líneas diferentes: “Petición”, “Respuesta”, “Datos” y “Desconocida”. En esta clasificación se contemplan todas las líneas descritas anteriormente además de un nuevo tipo que utilizaremos para aquellas líneas que no cumplan con el patrón de los otros tres tipos, de este modo, cumplimos con el objetivo de mantener el conjunto de datos completo sin pérdida de datos aunque recibamos líneas con formados no esperados. Utilizaremos una clave compuesta que consistirá en la fecha en la que se ha generado la línea convertida a bytes concatenado con la cadena de caracteres que representa el tipo de línea “Petición”, “Respuesta”, “Datos” o “Desconocida” utilizando como separador un byte a cero. Por otro lado, tenemos la tabla que almacena los resultados, “result”. Esta tabla tiene una estructura similar a la que comentábamos en la primera versión, estando compuesta por una column family con dos columnas para todas las líneas: - tproc: representa el tiempo de procesamiento. - npet: representa el número de peticiones. Insertaremos una línea por cada minuto y tipo de operación al igual que hemos comentado anteriormente con lo que utilizaremos la misma estructura de clave que en la tabla “log”, en este caso la cadena de caracteres representa el tipo de operación en lugar del tipo de línea y la fecha representa el minuto para el que se está realizando la agregación. Crearemos una vista en Phoenix que mapeará la tabla “result” de HBase, de este modo ofreceremos exactamente la misma interfaz SQL que en el caso anterior en el que utilizábamos Hive. 5.2.3. Software de procesamiento En esta sección expondremos el funcionamiento de la capa de procesamiento a un mayor nivel de detalle. En la figura 5.13 se pueden ver lar transformaciones y las acciones que se llevan a cabo para obtener los resultados a partir del flujo de datos de entrada. Figura 5.13: Transformaciones Spark Streaming Diseño Página 81 de 123 1. map: transforma los datos que se reciben de Flume serializados con Avro en un conjunto de cadenas de caracteres que representan las líneas sin serializar. 2. map: a partir de cada una de las líneas se crea un objeto dotando de estructura al RDD. 2.1. foreach: se almacenan los datos en el conjunto de datos maestro. 3. filter: se filtran los datos con el fin de mantener únicamente las líneas asociadas a las respuestas que son las líneas que contienen información acerca del tiempo de procesamiento invertido en cada operación. 4. mapToPair: por cada línea se crea un par clave-valor, la clave se forma con la fecha truncada a los minutos y el tipo de operación, por otro lado, el valor contiene el tiempo de procesamiento para la línea que se está procesando y se inicializa el número de operaciones a 1. 5. reduceByKey: para todas las claves iguales (mismo tipo de operación y mismo minuto) se suman los tiempos de procesamiento y el número de peticiones. 6. map: por último, se convierten los pares clave valor a un único tipo de datos con la misma estructura que la tabla en la que se almacenaran en HBase, un objeto con cuatro atributos: tipo de operación, fecha, tiempo de procesamiento y número de peticiones. 6.1. foreach: se almacenan los resultados en la tabla “result”. 5.3. Nodos Sistema de Dispensación Electrónica En el requisito RCA_003 se recoge que se debe desarrollar una aplicación que simule el funcionamiento del sistema de Dispensación Electrónica puesto que no tendremos acceso al sistema real. Además, en el requisito RAP_001 se especifica que el registro de las líneas de log se debe realizar a través de la herramienta log4j. El sistema de Dispensación Electrónica interactuará con el analizador de logs a través de la capa de recolección con lo que únicamente necesitamos poder enviar las líneas de log a través de Flume. Tal y como veremos en capítulo de implementación, es posible integrar log4j con Flume simplemente modificando los ficheros de configuración de log4. Para realizar la simulación del sistema de Dispensación Electrónica contamos con ficheros de log generados por el sistema real durante unas catorce horas. Estos ficheros de log los tenemos almacenados con la estructura que se muestra en la figura 5.14: Diseño Página 82 de 123 Figura 5.14: Estructura de carpetas de logs Por cada uno de los cuatro nodos que componen el sistema de Dispensación Electrónica tenemos una carpeta que contiene los ficheros de log generados por ese nodo. Dentro de esta carpeta tenemos los log generados por las dos instancias que se están ejecutando en cada nodo. Como se puede ver en la imagen los nombres de los ficheros contienen el código “s44ac1” o el código “s44bc1”, que nos permite diferenciar entre los ficheros generados por cada una de las instancias. Además, en el nombre se incluye la fecha en que han sido generados y el número de secuencia del fichero dentro de esa fecha ya que se sigue una política de rotación por la que cada uno de los ficheros ocupa 10 MB, una vez se ha alcanzado este límite se almacenan las nuevas líneas en un nuevo fichero. Crearemos cuatro contenedores Docker que simularan el funcionamiento de cada uno de los nodos. En cada contenedor se ejecutará una aplicación que leerá los datos de una carpeta y enviará las líneas a la hora indicada en el primer campo de cada una. De este modo, los datos se generarán a la misma velocidad que el sistema de Dispensación Electrónica original. En la figura 5.15 se puede ver un diagrama de flujo en el que se describe este proceso. Diseño Página 83 de 123 Figura 5.15: Diagrama de flujo de envío de líneas de log En primer lugar abrimos el fichero y leemos una línea, a continuación se lee la fecha y se actualiza el día, mes y año al actual, por último se planifica el envío para esa fecha. Este proceso se ejecuta hasta que se han programado para su envío las 1000 primeras líneas. En caso de que se alcance el final de fichero se debe abrir el siguiente por orden según la política de rotación que ya hemos comentado. Cuando se alcance el final del último fichero el algoritmo termina. Hasta este punto tenemos programadas las 1000 primeras líneas, cuando una línea sea enviada, se programa una nueva línea siguiendo el mismo proceso. De este modo se busca tener siempre en torno a 1000 líneas programadas (en el momento en que una se envía y hasta que se lea la siguiente no hay exactamente 1000 líneas programadas) que actúan a modo de buffer para que no haya problemas en el caso en que se deban enviar las líneas a un ritmo mayor al de lectura. Este algoritmo se debe ejecutar dos veces en cada nodo, una para cada una de las instancias del sistema de Dispensación Electrónica. 5.4. Nodos del clúster Hadoop Como distribución de Hadoop seleccionaremos Hortonworks Data Platform (HDP), concretamente la versión 2.2, la última disponible en el momento de realizar este proyecto. Esta elección la hemos realizado, principalmente, pensando en el despliegue del clúster en contenedores Docker [38]. Existe una startup denominada SequenceIQ que ofrece una serie de productos que Diseño Página 84 de 123 ayudan a desplegar un clúster Hadoop sobre contenedores Docker en la nube. La distribución con la que trabajan es precisamente con la producida por Hortonworks y, de hecho, durante la realización de este proyecto SequenceIQ ha sido adquirida por parte de la propia Hortonworks [39], lo que demuestra el interés de esta distribución en facilitar el despliegue de Hadoop utilizando contenedores como tecnología de virtualización. Además HP mantiene una relación muy estrecha con Hortonworks siendo uno de los principales miembros de su programa de partners. 5.5. Sistema de monitorización Como ya hemos comentado, desarrollaremos un sistema de monitorización del sistema con el fin de poder comprobar que todo funciona según lo esperado. Para poder medir si el ritmo de procesamiento es lo suficientemente rápido como para poder soportar la carga a la que se está sometiendo el sistema, inspeccionaremos el nivel de ocupación de los canales en los agentes Flume. Un nivel alto de utilización indicará que el ritmo de procesamiento es muy inferior al de generación. Además, con el fin de comprobar que no se ha producido pérdida de datos desde su generación hasta su almacenamiento en HBase comprobaremos el número de eventos enviados y recibidos con éxito de cada agente, esto nos permitirá averiguar en qué punto se están perdiendo dichos datos. Para la implementación de este sistema utilizaremos las funcionalidades que ofrece Flume, en concreto, la posibilidad de levantar un servidor HTTP que devuelva el estado actual del agente. Implementaremos una aplicación Java que consulte este estado en periodos de tiempo regulares y vuelque la información en un fichero. Posteriormente podremos analizar estos datos y concluir si las pruebas se han realizado o no con éxito. Para analizar los datos utilizaremos un script Python que genere gráficos acerca del tamaño de los canales (requisito RDI_007) y otro acerca de los eventos enviados y recibidos (requisito RDI_007). 5.6. Aplicación web En el requisito RDI_001 se establece la necesidad de crear una serie de informes predefinidos que se pongan a disposición de los usuarios a través de una aplicación web. En esta sección nos centraremos en el diseño de esta aplicación. Implementaremos un API de servicios REST que permita el acceso a estos informes en formato HTML. Los informes se generarán a partir de una serie de ficheros de definición creados con la herramienta Report Designer. Además los usuarios podrán definir nuevos informes a través de esta herramienta utilizando la configuración que explicaremos en la sección de implementación, con esto cumplimos con el requisito RAP_003. Además, la implementación de un API como método de publicación de informes facilitará la integración en un sistema mayor en el que se pueda mostrar un cuadro de mando con información acerca de múltiples sistemas y no solo del sistema de Dispensación Electrónica. Implementaremos un patrón modelo-vista-controlador (MVC) en el que el papel de modelo lo jugará una aplicación Java, el controlador será una clase que exponga los métodos de acceso a través de HTTP utilizando el framework de creación de servicios REST Jersey y que invocará los métodos del modelo para generar los informes. Por último, implementaremos la vista utilizando una página HTML basada en el framework Bootstrap y accederemos a los servicios REST a través de JQuery. A la hora de implementar el modelo utilizaremos una fachada que dará acceso a todas las funcionalidades de generación de informes y que implementará un patrón singleton con el fin de que exista, como máximo, una única instancia de esta clase. Utilizaremos la clase Reporte como un VO (value object) en el que se encapsula la ruta en la que se encuentra la definición del informe y los parámetros que se deben utilizar a la hora de generar dicho informe. Las demás clases se utilizan para generar el informe utilizando el SDK de Pentaho Reporting [40] y encapsular el resultado en formato Diseño Página 85 de 123 HTML. En la figura 5.16 se muestra el diagrama de clases de aplicación web, las clases sombreadas en un color más oscuro representan clases propias del SDK. Figura 5.16: Diagrama de clases de aplicación web En la figura 5.17 se muestra un diagrama de secuencia para la creación del informe acerca del uso del sistema desglosado por operación (explicaremos el contenido de este informe en detalle al final de esta sección). La clase InformesResource juega el papel de controlador en nuestra arquitectura MVC, y por lo tanto, es el encargado de atender las peticiones de las vistas. Además, hemos incluido un objeto denominado SDK que representa el SDK de Pentaho con el fin de poder mostrar con mayor claridad el funcionamiento del programa sin la necesidad de representar todas las clases que lo conforman ganando, de este modo, en claridad en el diagrama. Diseño Página 86 de 123 Figura 5.17: Diagrama de secuencia generación de informes 5.6.1. Operaciones por unidad de tiempo Uniremos los requisitos de difusión de la información RDI_004 y RDI_005 en un único informe que contendrá un gráfico asociado al número de operaciones por franja horaria durante día actual y otro gráfico que contendrá el número de operaciones por minuto durante la hora actual. Este informe estará disponible a través de la siguiente URL (suponiendo que la aplicación se encuentra desplegada en localhost con puerto 8080): http://localhost:8080/Reporting/api-informes/1.0/informes/carga - Devuelve el informe comentado anteriormente a partir de los datos actuales en formato HTML. - No acepta ningún parámetro adicional de entrada. 5.6.2. Uso del sistema por operación En el requisito RDI_006 se expone la necesidad de un informe que recoja la actividad del sistema desglosado por cada tipo de operación. Por ello, diseñaremos un informe que contiene una tabla en la que para cada uno de los tipos de operación (filas) incluiremos el tiempo de procesamiento, el número de peticiones y el tiempo de procesamiento medio para cada operación. Este informe será parametrizado de tal forma que aceptará el intervalo de tiempo en el que se tendrán en cuenta los datos. En este caso la URL será la siguiente: http://localhost:8080/Reporting/api-informes/1.0/informes/operaciones Diseño Página 87 de 123 - Devuelve el informe comentado anteriormente a partir de los datos actuales en formato HTML. - Parámetros: o inicio: fecha de inicio desde la que se tendrán en cuenta los datos. Debe estar en formato “dd-MM-yyyy hh:mm”. o fin: fechas de fin hasta la que se tendrán en cuenta datos. Debe ser posterior a la fecha de inicio y estar en formato “dd-MM-yyyy hh:mm”. Implementación Página 94 de 123 Figura 6.2: Página principal Ambari Abajo a la izquierda, en Actions tenemos un desplegable que nos permite instalar nuevos servicios en el clúster a través de la opción Add Service. A continuación nos saldrá una ventana emergente en la que podremos seleccionar el servicio que deseamos instalar, en este caso seleccionamos Flume. Figura 6.3: Instalar nuevos servicios Dejaremos todas las configuraciones con su valor por defecto a excepción de la configuración de los componentes del agente Flume tal y como se puede ver en la siguiente figura. Este agente será el encargado de agregar en un único flujo los datos los cuatro agentes Flume de los nodos del sistema de Dispensación Electrónica y utilizará tanto un sumidero como una fuente que manejan eventos serializados en Avro. Como capacidad máxima del canal hemos seleccionado 2.000.000 eventos, esto, tal y como veremos a continuación en la descripción de los agentes del sistema de Dispensación Electrónica nos permitiría almacenar todos los eventos generados en un día. Se trata de la misma Implementación Página 95 de 123 capacidad con la que cuentan, en conjunto, los cuatro agentes de la capa anterior, de este modo, tras un periodo de un día de inactividad del clúster (periodo máximo para el que se garantiza que no ocurre pérdida de datos) todos los datos podrían pasar de los agentes de la primera capa a este agente dejando a los demás totalmente liberados para almacenar nuevos eventos que se generen. Figura 6.4: Configuración Flume Por último, el asistente de configuración mostrará un recordatorio informando de que ciertos servicios se deben reiniciar tras la instalación de Flume. Figura 6.5: Instalación finalizada 6.2. Sistema de Dispensación Electrónica A la hora de crear los contenedores que simularán el comportamiento del sistema de Dispensación Electrónica utilizaremos el siguiente fichero de definición para la creación de la imagen Docker. Implementación Página 96 de 123 #Nodos de DISEL FROM ubuntu:14.04 RUN \ apt-get update && \ apt-get install -y openjdk-7-jre ADD apache-flume-1.6.0-bin /usr/local/bin/apache-flume-1.6.0-bin ADD disel.jar /usr/local/bin/ ADD flume.sh /usr/local/bin/apache-flume-1.6.0-bin/ ADD flumeDisel.conf /usr/local/bin/apache-flume-1.6.0-bin/ ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64 Código 6.4 Esta imagen se basa en la imagen oficial de Ubuntu, concretamente la versión 14.04 y se instala el OpenJDK para poder ejecutar tanto Flume como la aplicación Java que registrará las nuevas líneas de log. A continuación se añaden los ficheros necesarios (que deben estar presentes en el directorio en el que se encuentra el fichero de definición de la imagen), describiremos estos ficheros a continuación: - apache-flume-1.6.0-bin: se trata de la distribución de Flume utilizada. - disel.jar: consiste en la aplicación que hemos desarrollado para simular el funcionamiento del sistema de Dispensación Electrónica tal y como hemos descrito en la sección de diseño. Como ya hemos comentado, los log se deben enviar a través de la herramienta log4j, para ello utilizaremos el siguiente fichero de configuración: <?xml version="1.0" encoding="UTF-8"?> <Configuration status="warn" name="DISEL" packages=""> <Appenders> <Flume name="eventLogger" compress="false"> <Agent host="127.0.0.1" port="8585"/> <PatternLayout pattern="%m%n"/> </Flume> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="eventLogger"/> </Root> </Loggers> </Configuration> Código 6.5 De este modo se configura log4j de tal modo que las líneas de log se envían al agente Flume desplegado en localhost al puerto 8585. - flume.sh: se trata de un script en el que se encuentra el siguiente comando: /usr/local/bin/apache-flume-1.6.0-bin/bin/flume-ng agent --conf /usr/local/bin/apache-flume-1.6.0-bin/conf --conf-file flumeDisel.conf --name agent Implementación Página 97 de 123 -Dflume.root.logger=DEBUG,console -Dflume.monitoring.type=http -Dflume.monitoring.port=34545 Código 6.6 En este comando se utiliza el fichero de configuración que describiremos en el siguiente punto para desplegar el agente Flume. Además, con las últimas opciones se despliega de forma automática un servidor HTTP que atiende peticiones en el puerto 34545 y que devuelve información acerca de las estadísticas de ejecución del agente. Utilizaremos esta información en la sección de pruebas con el fin de validar el correcto funcionamiento del sistema. - flumeDisel.conf: mediante este fichero se definen los componentes del agente Flume que se desplegará: agent.channels = ch-1 agent.sources = src-1 agent.sinks = sink-1 agent.channels.ch-1.type = file agent.channels.ch-1.capacity = 500000 agent.sources.src-1.type = avro agent.sources.src-1.bind = 0.0.0.0 agent.sources.src-1.port = 8585 agent.sources.src-1.channels = ch-1 agent.sinks.sink-1.type = avro agent.sinks.sink-1.hostname = amb0 agent.sinks.sink-1.port = 1234 agent.sinks.sink-1.channel = ch-1 Código 6.7 Definimos un canal que almacena los eventos en un fichero tal y como hemos especificado en el diseño, cumpliendo con el requisito RCA_002 que establece un periodo de un día de inactividad del clúster durante el que no se deben producir pérdidas de datos. En el apartado de análisis, a partir de los datos de log de los que disponemos, estimamos un volumen cercano a los 2.000.000 de líneas por día, por lo tanto, estableceremos un tamaño de canal que nos permita almacenar todos estos eventos, en concreto, dividiremos este volumen total entre los cuatro agentes con lo que tenemos un total de 500.000 eventos. Utilizaremos tanto una fuente como un sumidero que utilizan Avro para la serialización de los eventos recibidos de log4j y de los eventos enviados a la siguiente capa. 6.3. Sistema de procesamiento El sistema de procesamiento representa el núcleo del proyecto que estamos desarrollando. Se trata de una aplicación Java que se ejecuta sobre Spark de forma distribuida en el clúster. En esta sección comentaremos alguno de los puntos más relevantes de la implementación de este sistema. Con el siguiente código se crea el DStream con los datos de entrada provenientes de Flume y, a continuación, se ejecuta un map sobre el conjunto de datos de entrada que extrae las líneas de log de los eventos Flume que, como ya hemos comentado, se encuentran serializados mediante Avro. Implementación Página 98 de 123 JavaReceiverInputDStream<SparkFlumeEvent> flumeStream = FlumeUtils .createStream(ssc, host, puerto); JavaDStream<String> lineasString = flumeStream .map(new Function<SparkFlumeEvent, String>() { public String call(SparkFlumeEvent flumeEvent){ AvroFlumeEvent avroEvent = flumeEvent.event(); ByteBuffer bb = (ByteBuffer) avroEvent.get(avroEvent .getSchema().getField("body").pos()); String cadena = new String(bb.array()); return cadena; } }); Código 6.8 Modificando este código podemos cambiar el origen de los datos y establecer, por ejemplo, HBase. De este modo podríamos implementar un componente encargado del reprocesado de los datos tal y como mencionábamos en el diseño. Cuando se libere una nueva versión del analizador, basta con desplegar el mismo programa con el método de entrada modificado para leer de HBase y poder tener los resultados que calcula la nueva versión a partir de todo el histórico que tenemos almacenado. Realizando sucesivas transformaciones, tal y como se muestra en los diagramas propuestos en la sección de diseño, obtenemos el conjunto de datos resultado que debemos almacenar en HBase, para ello utilizamos el siguiente código: resultados.foreach(new Function<JavaRDD<Resultado>, Void>(){ public Void call(JavaRDD<Resultado> rdd) throws IOException{ DaoResultados dao = new DaoResultados(); for(Resultado r : rdd.collect()) dao.insertar(r); return null; } }); Código 6.9 En este código se itera sobre todos los RDD que forman el DStream y se almacena el contenido en HBase a través de la clase DaoResultados. Cabe destacar que este objeto de acceso a datos se instancia directamente en lugar de utilizar el patrón DAO en conjunto con AbstractFactory tal y como haríamos en una aplicación convencional. Como ya hemos comentado, Spark Streaming se basa en el concepto de micro batch con lo que, esta porción de código se ejecuta constantemente para pequeñas cantidades de datos. Con lo que se necesita que el proceso de instanciación de los recursos suponga el menor overhead posible. Una alternativa en una aplicación convencional sería instanciar el objeto fuera de esta sección de código y pasar directamente el objeto ya instanciado todas las veces que sea necesario. En Spark no podemos enviar este tipo de parámetros a las funciones que se ejecutan en las transformaciones o en las acciones (como es este caso) o utilizar objetos que se instancian fuera de la definición de dichas funciones. Esto es razonable puesto que tendremos una gran cantidad de nodos ejecutando estas funciones de forma transparente con lo que se podría producir condiciones de carrera que obligarían a adoptar medidas extra de gestión de concurrencia, como semáforos o mutex, que restarían flexibilidad a la hora de planificar las tareas dentro del clúster. Implementación Página 99 de 123 Esta aplicación la hemos desarrollado de tal forma que se puede configurar a través del fichero /compartida/resources/config.properties. Este fichero tiene el siguiente formato: #Conexión host=”Dirección IP del Host en el que se ejecuta el agente Flume” puerto=”Puerto que hemos establecido en la configuración del sumidero (sink)” #Duración duracion=”Duración de cada microbatch en milisegundos” Código 6.10 dónde host y puerto establecen los parámetros de conexión con el agente Flume y duracion establece la duración de cada batch, esto dependerá de las capacidades de cómputo disponibles y de la complejidad asociada al procesamiento. En nuestro caso estableceremos este valor a 5000, es decir 5 segundos. Como ya hemos comentado, Spark ofrece la posibilidad de ejecutarse sobre un clúster gestionado con YARN como es el nuestro. Con el siguiente comando podemos ejecutar nuestra aplicación utilizando YARN como gestor de recursos: spark-submit --class com.hp.ereceta.analizador.procesamientoLog.ProcesamientoLog --master yarn-cluster /compartida/analizador_1.0.jar Comando 6.8 6.4. Definición de informes A continuación definiremos el proceso de generación de la definición de informes con la herramienta Pentaho Report Designer, posteriormente cargaremos estas definiciones desde la aplicación web para poder generar los informes finales que se presentarán al usuario. Desde la ventana principal seleccionamos File > New y se abrirá una pestaña con una nueva definición de un informe en blanco tal y como se muestra en la siguiente captura de pantalla: Implementación Página 100 de 123 Figura 6.6: Ventana principal Pentaho Report Designer Deberemos configurar un nuevo origen de datos que utilizaremos para la generación de los informes, en nuestro caso lo configuraremos con los parámetros de conexión de Phoenix. Para ello accedemos a Data > Add Datasource > JDBC, una vez hecho esto creamos una nueva fuente de datos a través del botón . Utilizaremos los siguientes parámetros de configuración: Figura 6.7: Configuración Datasource Por último, necesitamos añadir el driver de Phoenix para que Pentaho Report Designer pueda establecer la conexión y encontrar la clase org.apache.phoenix.jdbc.PhoenixDriver que hemos establecido en la ventana anterior. Para ello, copiamos el fichero phoenix-client.jar que podemos encontrar en la carpeta de instalación de Phoenix dentro de alguno de los nodos de clúster Hadoop y lo copiamos en la carpeta de instalación de Pentaho Report Dsigner en la ruta lib/jdbc/. De este modo Implementación Página 101 de 123 ya tendremos acceso a los datos que se encuentran almacenados en el clúster Hadoop, únicamente necesitaremos definir las consultas SQL a través de las cuales obtendremos los datos para la generación de nuestros informes. En la ventana de creación de un nuevo Datasource que vemos a continuación también tenemos disponible un editor SQL que nos permite asociar consultas a cada Datasource. Figura 6.8: Editor SQL Para el primer informe que recoge el número de peticiones por unidad de tiempo definiremos dos consultas, una para la gráfica de actividad para el día completo y otra únicamente para la hora con el resumen de peticiones por minuto. En el primer caso la consulta es la siguiente: SELECT "hora", COALESCE(SUM(R."npet"),0) AS "peticiones" FROM (SELECT "fecha", "npet" FROM "result" WHERE "fecha" > trunc(CURRENT_TIME(), 'DAY')) AS R RIGHT JOIN "todasHoras" ON "hora" = CAST(to_number(to_char(R."fecha", 'HH')) AS INTEGER)%24 GROUP BY "hora" Código 6.11 Esta consulta utiliza una tabla auxiliar denominada todasHoras que mantiene una fila por cada una de las horas del día, esto nos permite establecer a 0 aquellas horas para las que no hay peticiones registradas y no provocar discontinuidades en la gráfica del informe. Las limitaciones del lenguaje SQL soportado por Phoenix, actualmente, hace que sea necesaria la utilización de este tipo de tablas auxiliares para algunos tipos de consultas. Implementación Página 102 de 123 En el caso de la segunda consultas se aplica un razonamiento similar utilizando una tabla denominada todosMinutos. SELECT "minuto" AS "minuto", COALESCE(SUM(R."npet"),0) AS "peticiones" FROM (SELECT "fecha", "npet" FROM "result" WHERE "fecha" > trunc(CURRENT_TIME(), 'HOUR')) AS R RIGHT JOIN "todosMinutos" ON "minuto" = to_number(to_char(R."fecha", 'mm')) GROUP BY "minuto" Código 6.12 Para el segundo informe que recoge el resumen de número de peticiones por operación y el tiempo de procesamiento de dicado a cada una de ellas utilizaremos la siguiente consulta: SELECT "operacion", SUM("npet") AS "peticiones", SUM("tproc") AS "tiempo", AVG("tproc"/"npet") AS tmedio FROM "result" WHERE "fecha" BETWEEN to_date(${fechaInicio}, 'yyyy-MM-dd HH:mm:ss') AND to_date(${fechaFin}, 'yyyy-MM-dd HH:mm:ss') GROUP BY "operacion" ORDER BY "peticiones" DESC Código 6.13 Esta consulta se encuentra parametrizada por los argumento fechaInicio y fechaFin. De este modo podremos pasar estos parámetros desde la aplicación web de tal forma que el usuario podrá definir el periodo de tiempo sobre el que se realizará el resumen. Por último, únicamente deberemos añadir los componentes gráficos deseados que tenemos disponibles en la paleta situada en la parte izquierda de la ventana principal. Almacenaremos estas definiciones en ficheros .prpt que posteriormente cargaremos desde la aplicación web con las utilidades de Pentaho Reporting Engine SDK [40]. En todo caso, siguiendo el mismo procedimiento que hemos definido para la generación de las definiciones de estos informes podemos generar informes ad hoc totalmente personalizados, pudiendo aprovechar las posibilidades de exportación a diversos formatos como PDF o HTML que ofrece Pentaho Report Designer cumpliendo con lo establecido en el requisito RAP_003. Estos informes se podrán crear a partir de la tabla con los resultados preprocesados o a partir de los datos completos que tenemos almacenados en HBase, en este caso sería necesario crear nuevas vistas en Phoenix que den acceso a estos datos a través de SQL. La aplicación web se desplegará en un contenedor Docker basado en la imagen definida por el siguiente fichero de definición: FROM tomcat:8.0 ADD Reporting.war /usr/local/tomcat/webapps/ Código 6.14 Como se puede ver, se trata de una imagen muy simple basada en la imagen oficial de Tomcat 8.0. Únicamente añadiremos la aplicación web en la ruta correspondiente para que se despliegue en Implementación Página 103 de 123 el contenedor de aplicaciones. En primer lugar debemos crear la imagen con el siguiente comando en la carpeta en la que se encuentra el fichero anterior: $ docker build -t reporting:1.0 . Comando 6.9 Para ejecutarlos únicamente necesitamos el siguiente comando y el servidor de aplicaciones se ejecutará en el contenedor: $ docker run -it reporting:1.0 Comando 6.10 Pruebas Página 110 de 123 Con el fin de comprobar que efectivamente se cumple con lo especificado en el requisito RDI_002 crearemos un nuevo informe totalmente diferente de los que hemos comentado. Para ello definiremos una nueva vista en Phoenix que nos permita acceder a las líneas que tienen datos asociados acerca de la farmacia y los pacientes con los que se relaciona la operación. Crearemos esta vista con la siguiente sentencia SQL: CREATE VIEW "log" ( "fecha" UNSIGNED_TIMESTAMP NOT NULL, "operacion" VARCHAR NOT NULL, "fmcia" VARCHAR, "fmtico" VARCHAR, "tdoc" VARCHAR, "doc" VARCHAR, CONSTRAINT pk PRIMARY KEY("fecha", "operacion") )default_column_family='campos'; Código 7.1 A partir de estos datos generaremos el informe que se muestra en la figura 7.7 y que recoge un análisis de las peticiones relacionadas con cada paciente. En primer lugar, mostramos un gráfico con los 5 pacientes que han originado un mayor número de peticiones, a continuación, se muestra una tabla en la que se pueden ver los pacientes que han generado peticiones desde un mayor número de farmacias diferentes. Pruebas Página 111 de 123 Figura 7.7: Informe ad hoc Como se puede ver, se trata de un informe radicalmente diferente a los anteriores y que utiliza el conjunto de datos originales en lugar de los datos preprocesados. Además, el interés principal de este informe no es ver si la actividad que está registrando el sistema de Dispensación Electrónica es adecuado sino que se centra más en la faceta de análisis social acerca de cómo los pacientes interactúan con este sistema. Esto muestra el amplio rango de casos de aplicación que tiene este proyecto más allá de comprobar el correcto funcionamiento del sistema de Dispensación Electrónica. Haciendo un breve análisis de este último informe podemos ver como existe un paciente que ha acudido a 30 farmacias diferentes. Para generar este informe estamos teniendo en cuenta la totalidad de los datos de los que disponemos y que apenas abarcan unas 14 horas. Vemos como se trata de un número de farmacias diferentes bastante elevado en relación al periodo de tiempo que estamos analizando, esto también lo podemos aplicar tanto al segundo paciente de la lista como al tercero. Para poder sacar conclusiones tendríamos que realizar un estudio en mayor profundidad en busca, por ejemplo, de alguna correlación entre las farmacias visitadas o las franjas horarias en que se han dado estas visitas. También podemos ver como el paciente que más peticiones ha originado, DOC04787, no aparece en la lista de pacientes con mayor número de farmacias visitadas, esto nos indica que en muy pocas farmacias (como mucho en 3) se han realizado un gran número de peticiones acerca de este paciente. Al igual que el caso anterior sería necesario un análisis más profundo para Pruebas Página 112 de 123 poder extraer alguna conclusión. En todo caso, el objetivo de este informe es demostrar que se puede extraer una gran variedad de información de nuestro sistema más allá de los informes que hemos previsto en este proyecto. La generación de nuevos informes tiene una penalización importante con respecto a los que ya están definidos puesto que deben acceder a la totalidad de los datos en lugar de a un pequeño subconjunto de resultados preprocesados. En los datos que hemos manejado para la realización de estas pruebas hemos pasado de un total de 547.903 filas (una por cada una de las líneas de log) a 5.841 filas en la tabla de resultados preprocesados. Esto supone que acceder a los datos preprocesados representa alrededor de un 1% con respecto a los datos originales. A la necesidad de acceder a un número mucho mayor de datos, en estos nuevos informes, tenemos que sumar el tiempo empleado en realizar todas las computaciones asociadas a las funciones de agregación que ya tenemos calculadas en la tabla de resultados. Por la naturaleza de estas pruebas, no se ha probado el sistema durante periodos largos de tiempo como pueden ser varios día o incluso semanas que pueden evidenciar algún tipo de problema no detectado. Además, en un entorno real, la carga que debe soportar será sensiblemente mayor ya que, potencialmente, tendremos un gran número de clientes realizando varias peticiones en paralelo tanto de informes predefinidos como de nuevos informes con el consiguiente incremento de los recursos necesarios. Todo esto hace que sea conveniente la realización de una minuciosa monitorización sometiendo al sistema a una situación de carga similar a la que nos encontraremos en un entorno de producción con el fin de asegurar el correcto funcionamiento. Conclusiones Página 113 de 123 8. Conclusiones A pesar de que, como ya hemos comentado, sería necesario un periodo de pruebas mayor y más ambicioso en el que se pudiera someter al sistema a una situación de carga real durante un mayor periodo de tiempo, podemos concluir que se han alcanzado los objetivos originales al desarrollar un sistema de procesamiento de log en tiempo real plenamente funcional. Más allá del software concreto desarrollado, hemos llevado a cabo un análisis tecnológico y una propuesta de diseño de una arquitectura mucho más general aplicable a una gran variedad de sistemas de procesamiento Big Data en tiempo real. Una de las fortalezas del sistema propuesto radica precisamente en su versatilidad y facilidad de adaptación a nuevas características y requisitos sin tener que realizar grandes cambios tal y como comentaremos en la siguiente sección dedicada exclusivamente a las posibles ampliaciones. La propuesta de una arquitectura alternativa, basada en los mismos principios que la arquitectura lambda, nos ha permitido integrar diversas herramientas del ecosistema Hadoop para formar un sistema robusto y mantenible. Esta labor de diseño e integración representa uno de los principales valores del presente proyecto puesto que es susceptible de ser reutilizado en futuros desarrollos con la consiguiente reducción de los costes asociados. En lo que se refiere a la capa de almacenamiento, hemos conseguido integrar todas las ventajas asociadas a una base de datos NoSQL, como es HBase, sin dejar de proporcionar una interfaz SQL de acceso a datos de cara a los clientes. Esto nos ha permitido conseguir un sistema de almacenamiento de alto rendimiento sin renunciar a la gran compatibilidad con terceros sistemas y de capacidad de análisis que ofrece el estándar SQL. Conseguimos así utilizar una herramienta propia del business intelligence tradicional como es Pentaho Report Designer en un entorno Big Data en el que los datos se encuentran en una base de datos no relacional. Más allá del procesamiento en tiempo real con Spark Streaming, Spark está ganando en popularidad y se está convirtiendo en una alternativa de futuro a MapReduce como principal sistema de procesamiento batch en Hadoop. Un claro ejemplo lo tenemos en los objetivos marcados desde el equipo de desarrollo de Hive que planean utilizar Spark como nuevo motor de ejecución de consultas HiveQL. Esto, unido al gran crecimiento que están experimentando otros componentes como Spark SQL y MLlib hace que las posibilidades de esta plataforma crezcan enormemente a corto y medio plazo. Todas estas circunstancias dan especial valor al análisis realizado sobre Spark puesto que las expectativas actuales indican que el potencial de ser utilizado en nuevos proyectos es muy alto. Precisamente, la capa de procesamiento representa el núcleo del sistema que hemos desarrollado y se beneficia de las funcionalidades que ofrecen todas las demás herramientas que hemos utilizado. En este sentido, la integración de Spark Streaming con Flume y HBase consiste en una de las claves de cualquier sistema de procesamiento en tiempo real en entornos Hadoop. En lo que se refiere al envío de datos, hemos analizado y comparado las dos principales alternativas que existen actualmente: Flume y Kafka. El análisis de las principales ventajas que aporta cada uno de ellos, así como la experiencia adquirida al utilizar Flume en un sistema concreto, podrá ser de especial relevancia en futuros proyectos a la hora de seleccionar la herramienta más adecuada minimizando los riesgos asociados a la selección tecnológica. La utilización de un sistema de virtualización ligero como es Docker nos ha permitido desarrollar un sistema con un consumo de recursos muy asumible que puede ser susceptible de ejecutarse directamente en los mismos nodos que el sistema principal. Se trata de un sistema auxiliar cuya misión es la monitorización de un sistema principal, con lo que el consumo de recursos se debe mantener lo más ajustado posible ya que no es aceptable un sistema de monitorización cuyos costes superen a los del propio sistema que se está monitorizando. En este sentido, la posibilidad de que Conclusiones Página 114 de 123 ambos sistemas se ejecuten en un mismo entorno dependerá en gran mediad del nivel de utilización de los recursos disponibles por parte del sistema principal. La constante evolución de todo el ecosistema Hadoop, especialmente de alguno de los proyectos que hemos utilizado como puede ser Phoenix que aún no cuentan con un gran nivel de madurez, abren nuevas alternativas de futuro a la hora de aplicar el sistema propuesto a un mayor rango de casos de aplicación. Esto es especialmente aplicable al caso de Docker cuya creciente popularidad puede hacer que se convierta en una de las opciones más relevantes a la hora de desplegar servicios en la nube. Más allá de todos los conocimientos técnicos adquiridos tras el aprendizaje de un gran número de tecnologías y paradigmas nuevos, desde el punto de vista de la realización de un Trabajo Fin de Grado, es especialmente relevante la posibilidad de aplicar gran parte de los conocimientos y destrezas adquiridos durante el Grado en un proyecto de una envergadura considerable. En este sentido, cobran especial relevancia todas aquellas habilidades transversales a la gran mayoría de proyectos software como pueden ser las propias de la gestión de proyectos y el desarrollo de software de forma sistemática y con garantías. El hecho de tratarse de un proyecto con vocación de ser aplicado en un entorno de producción real, es especialmente enriquecedor para el alumno al permitir enfocar todas estas habilidades en la creación de un producto que pueda cubrir una necesidad real. 8.1. Ampliaciones Una de las principales ampliaciones serían las que afectan al sistema de procesamiento de log, utilizando la arquitectura propuesta y simplemente añadiendo nuevas transformaciones sobre el flujo de datos de entrada dentro de Spark Streaming podríamos llegar a obtener un conjunto más rico de resultados. Además, dado que todo el procesamiento se realiza utilizando Spark, se puede considerar la utilización de técnicas de machine learning soportadas por MLlib que permitan clasificar la actividad del sistema de Dispensación Electrónica de forma automática basándonos en los nuevos conjuntos de resultados, que contarán con mucha más información. Como resultado, podríamos llegar a conseguir una herramienta muy potente capaz de predecir la actividad del sistema permitiendo adelantarse a situaciones indeseadas antes de que se produzcan. En relación con lo anterior, la aplicación web también es susceptible de grandes mejoras puesto que, si contamos con una herramienta que nos permite clasificar la actividad de forma automática y en tiempo real, podemos ofrecer un servicio de alertas ante determinados patrones de tal forma que se ponga sobre aviso a los usuarios ante la posibilidad de que pueda ocurrir una determinada situación (por ejemplo el colapso del sistema). Además, manejar un conjunto de resultados más rico supone rediseñar los informes generados permitiendo producir cuadros de mando con un mayor número de indicadores. La interfaz gráfica también es susceptible de mejoras. Una de las principales sería una conversión automática de unidades de tal forma que los tiempos no se muestren siempre en milisegundos sino que se muestren en unidades mayores que faciliten su interpretación. En nuestra implementación se trata el sistema de Dispensación Electrónica como un único componente que emite datos cuando, en realidad, se trata de cuatro nodos independientes. Puede ser interesante, sobre todo pensando en la clasificación automática de la actividad, contar con información acerca de en qué nodo se ha registrado cada una de las líneas y poder ver de este modo el estado de cada uno por separado. Actualmente, en la implementación del sistema de Dispensación Electrónica real esto no se considera puesto que cada nodo genera sus log en una carpeta independiente y, por lo tanto, no es necesario incluir esta información como un campo especial dentro de cada línea. Podríamos modificar el formato de las líneas para que siempre incluyan este nuevo campo. No obstante, si no deseamos que el formato se deba modificar podemos optar por Conclusiones Página 115 de 123 añadir lo que se conoce en Flume como Interceptor. Los Interceptor ofrecen la posibilidad de modificar o eliminar eventos a medida que se reciben. Existen implementaciones predefinidas pero también se ofrece la posibilidad de crear nuevos Interceptor a partir de clases Java propias que implementen el interfaz org.apache.flume.interceptor.Interceptor. En nuestro caso, simplemente podríamos coger uno de los que ya viene implementado por defecto, Host Interceptor, cuya funcionalidad es precisamente la de añadir una cabecera con el nombre del host y la IP. En nuestro análisis de las pruebas realizadas, hemos tenido en cuenta cierta información acerca de la actividad de los nodos del sistema de Dispensación Electrónica por separado. Esto ha sido posible gracias a que contábamos con las estadísticas de uso de los agentes Flume. Esta información nos ha permitido entender mejor que estaba pasando en cada momento, lo que demuestra que esta ampliación en la capa de recolección de datos y, consecuentemente, en el capa de procesamiento, podría aportar gran valor añadido sobre la implementación actual. En todo caso, se utiliza la misma arquitectura base, únicamente se modifica la configuración de los agentes Flume para mantener en cada evento el nombre y la IP del nodo que lo envía y se rediseña el algoritmo que se ejecuta en la capa de procesamiento para dar soporte a las nuevas funcionalidades. Debemos tener en cuenta que un procesamiento más complejo de los resultados unido a la ejecución de los algoritmos de machine learning pueden tener un impacto significativo sobre el rendimiento obligando a aumentar el número de nodos del clúster, en todo caso, Spark en general, y tanto Spark Streaming como MLlib en particular, se han diseñado para escalar adecuadamente a medida que se aumentan los nodos del clúster. Anexos Página 116 de 123 9. Anexos 9.1. Instalación Docker A continuación describiremos el proceso de instalación de Docker, en nuestro caso utilizaremos un equipo que tiene instalado Ubuntu 13.10. En todo caso, en la propia documentación de Docker se recoge una guía de instalación muy completa en la que se comenta este proceso para múltiples sistemas y versiones. Instalaremos la última versión de Docker disponible, que en el momento de realizar este proyecto es la 1.7.1. 9.1.1. Prerrequisitos Docker, de forma oficial, únicamente ofrece soporte para sistemas de 64 bit. Además, en sistemas Linux necesita, como mínimo, la versión 3.10 del kernel. Para averiguar la versión que tenemos instalada simplemente podemos ejecutar el siguiente comando: $ uname –r 3.11.0-12-generic Comando 9.1 Como se puede ver, en nuestro caso contamos con una versión superior con lo que podremos continuar el proceso de instalación sin problema. 9.1.2. Instalación Ejecutando el siguiente comando se instalará la última versión de Docker: $ wget -qO- https://get.docker.com/ | sh Comando 9.2 Pedirá la clave de sudo con lo que el usuario debe tener los permisos necesarios. Con el fin de verificar la instalaciónde Docker podemos ejecutar el siguiente comando: $ sudo docker run hello-world Comando 9.3 Como se pude ver en la línea anterior, debemos ejecutar docker con sudo. Podemos evitar esto creando un grupo llamado docker y añadiendo los usuarios a dicho grupo. En todos los script que manejamos en este TFG no se incluye sudo con lo que, para que funcionen sin realizar ninguna modificación debemos realizar esta acción, para ello ejecutaremos el siguiente comando: $ sudo usermod -aG docker usuario Comando 9.4 Para que los cambios surtan efecto debemos cerrar sesión y volver a iniciarla, para comprobar que todo está configurado correctamente podemos ejecutar el siguiente comando: Anexos Página 117 de 123 $ docker run hello-world Comando 9.5 Anexos Página 118 de 123 9.2. Anonimizar log reales El requisito RCA_004 establece que a los efectos de la realización de este Trabajo Fin de Grado se deben manejar datos anonimizados, para ello desarrollaremos un script Python que se encargue de realizar dicha tarea. Utilizaremos datos reales anonimizados en lugar de conjuntos de datos sintéticos con el fin de poder imitar los más fielmente posible el funcionamiento real del sistema de Dispensación Electrónica y ver si nuestro sistema se comporta según lo esperado en bajo pruebas de carga reales. En la sección de análisis tecnológico se explican en detalle los formatos de las diferentes líneas de log que nos podemos encontrar. A continuación se pueden ver tres líneas ya anonimizadas que hacen referencia a la misma operación (el cuarto campo indica el id de la operación). 2015-04-29 22:05:09,214 | INFO | plataforma | [18c82e855a11c46e7d71b425f6abeab84c753bf7] | Petición | Servicio: ServicioDispensaciones | Operación: registroDispensacion_eReceita | Cliente: NCD 2015-04-29 22:05:10,792 | INFO | plataforma | [18c82e855a11c46e7d71b425f6abeab84c753bf7] | <datos><farmacia>FC00000</farmacia><farmaceutico>FT00000</farmaceutico><tipodocumento>C IP</tipodocumento><documento>DOC00000</documento><fuente>MANUAL</fuente></datos> 2015-04-29 22:05:21,072 | INFO | plataforma | [18c82e855a11c46e7d71b425f6abeab84c753bf7] | Respuesta | Servicio: ServicioDispensaciones | Operación: registroDispensacion_eReceita | Cliente: NCD | 5253 | 11859 El id se construye con información acerca de la operación (puede contener información como el identificador de la farmacia) con lo que este campo debe ser anonimizado, además anonimizaremos el identificador del farmacéutico, el identificador de la farmacia y el documento del paciente. Los demás campos los mantendremos sin modificar puesto que no contienen información sensible para los usuarios sino que únicamente informan acerca del funcionamiento del sistema. Para generar nuevos id en los datos anonimizados utilizaremos una función hash, en concreto SHA-1, de este modo, conseguiremos que los id´s iguales generen el mismo id con lo que no perderemos la relación entre las líneas que se refieren a una misma operación. A la hora de sustituir los demás campos no utilizaremos esta función hash puesto que supondría un drástico incremento en el tamaño de los ficheros de salida ya que la longitud de estos identificadores es, en general, muy inferior a la del identificador de la operación. En este caso utilizaremos un diccionario que nos permita sustituir campos iguales siempre por el mismo valor, en el caso de las farmacias y los farmacéuticos utilizaremos el patrón FCXXXXX y FTXXXXX respectivamente, donde cada X representa las cifras de un número incremental de tal forma que la primera aparición de una farmacia se sustituye por FC00000, a la siguiente le correspondería FC00001 y así sucesivamente. En el caso de los documentos de pacientes utilizaremos el patrón DOCXXXXX. De este modo, conseguimos ocultar todos los datos que puedan ser sensibles para los usuarios, por el contrario, mantenemos los patrones de uso del sistema de cada usuario (aunque no se relacione esta actividad con el identificador real de dicho usuario) así como de las farmacia y los farmacéuticos. A continuación mostraremos el seudocódigo utilizado: INICIO: farmacias = {} farmaceuticos = {} documentos = {} Anexos Página 119 de 123 PARA fichero EN listar_ficheros(): //algunos documentos de paciente contienen saltos de línea que es necesario eliminar para poder //procesar el fichero línea a línea y caracteres especiales no permitidos en XML como ‘<’ que también //es necesario eliminar para poder extraer los datos originales y anonimizarlos por eso necesitamos // un preprocesado preprocesado(fichero) lineas = leer_lineas(fichero) borrar_contenido(fichero) PARA linea EN contenido: campos = línea.split(“ | “) id = getId(campos[3]) //Extraer “id” de “[id]” campos[3] = '[' + sha1(id) + ']' SI contiene_datos(linea): datos = paserXML(campos[4]) SI datos.famaceutico != “”: SI datos.famaceutico en farmaceuticos datos.famaceutico = farmaceuticos[datos.famaceutico] SINO id = siguiente_id(farmaceuticos) farmaceuticos[datos.famaceutico] = id datos.famaceutico = id SI datos.farmacia != “”: SI datos.farmacia en farmacias datos.farmacia = farmacias[datos.farmacia] SINO id = siguiente_id(farmacias) farmacias[datos. farmacia] = id datos.farmacia = id SI datos.documento != “”: SI datos.documento en documentos datos.documento = documentos[datos.documento] SINO id = siguiente_id(documentos) documentos[datos. documento] = id datos.documento = id campos[4] = convertir_a_texto(datos) linea = " | ".join(campos) escribir_linea(fichero, linea) Fin