proyecto fin de carrera - universidad de...

157
Equation Chapter 1 Section 1 Proyecto Fin de Carrera Ingeniería de Telecomunicación Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en contenedores Autor: Jesús Álvarez Fernández-Nespral Tutor: Isabel Román Martínez Departamento de Ingeniería Telemática Escuela Técnica Superior de Ingeniería Universidad de Sevilla Sevilla, 2018

Upload: others

Post on 17-Jun-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Equation Chapter 1 Section 1

Proyecto Fin de Carrera

Ingeniería de Telecomunicación

Diseño y desarrollo de un servicio de información

demográfica en entorno Cloud basado en

contenedores

Autor: Jesús Álvarez Fernández-Nespral

Tutor: Isabel Román Martínez

Departamento de Ingeniería Telemática

Escuela Técnica Superior de Ingeniería

Universidad de Sevilla

Sevilla, 2018

Page 2: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 3: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

iii

Proyecto Fin de Carrera

Ingeniería de Telecomunicación

Diseño y desarrollo de un servicio de información

demográfica en entorno Cloud basado en

contenedores

Autor:

Jesús Álvarez Fernández-Nespral

Tutor:

Isabel Román Martínez

Departamento de Ingeniería Telemática

Escuela Técnica Superior de Ingeniería

Universidad de Sevilla

Sevilla, 2018

Page 4: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 5: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

v

Proyecto Fin de Carrera: Diseño y desarrollo de un servicio de información demográfica en entorno Cloud

basado en contenedores

Autor: Jesús Álvarez Fernández-Nespral

Tutor: Isabel Román Martínez

El tribunal nombrado para juzgar el Proyecto arriba indicado, compuesto por los siguientes miembros:

Presidente:

Vocales:

Secretario:

Acuerdan otorgarle la calificación de:

Sevilla, 2018

Page 6: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

El Secretario del Tribunal

Page 7: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

vii

A mi familia

A mis maestros

Page 8: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 9: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

ix

Agradecimientos

A todos los que con su infinita paciencia me han apoyado y animado en todo momento durante la realización

del proyecto.

Page 10: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 11: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

xi

Resumen

En el presente proyecto se muestra la transición de un servicio de información demográfica, utilizado en un

contexto de integración con el sistema sanitario, pero desarrollado en un entorno local y con un modelo

monolítico tradicional, para dotarlo de las capacidades necesarias para su consumo como servicio Web, y con

un alto grado de escalabilidad y facilidad de despliegue al estar basado en tecnología de contenedores.

Page 12: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 13: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

xiii

Abstract

This project shows the transition of a demographic information service, used in a context of health systems

integration, but developed in a local environment and with a traditional monolithic model, to provide it with the

necessary capacities for its consumption as a Web service, and with a high degree of scalability and ease of use,

being based on containers' technology.

Page 14: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 15: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

xv

Índice

Agradecimientos ix

Resumen xi

Abstract xiii

Índice xv

Índice de Tablas xviii

Índice de Figuras xx

1 Introducción 1 1.1 Contexto 1 1.2 Motivación y objetivos 6 1.3 Material empleado 7 1.4 Estructura del documento 8

2 Estado de la técnica 9 2.1 Servicio de Identificación Demográfico 9

2.1.1 PIDS 10 2.2 Servicios Web 14

2.2.1 Arquitectura de software distribuido 14 2.2.2 Componentes y estándares de los Servicios Web SOAP 16

2.3 Contenedores 23 2.3.1 Arquitectura de contenedores: similitudes y diferencias con máquinas virtuales 25 2.3.2 Escenarios de uso habituales 27 2.3.3 Componentes del kernel 27 2.3.4 Orquestación 28

2.4 Cloud Computing 32 2.4.1 Modelos de servicio 33 2.4.2 Cloud computing y contenedores - CaaS 33

3 Herramientas 35 3.1 XPath 35 3.2 PostgreSQL 35

3.2.1 Arquitectura básica 35 3.2.2 Por qué PostgreSQL 36

3.3 MyBatis 37 3.3.1 Utilización de MyBatis 37 3.3.2 Características adicionales 38

Page 16: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

3.3.3 Ventajas frente a herramientas ORM 38 3.4 API JAX-WS – proyecto Metro 39

3.4.1 Parte servidora JAX-WS 41 3.4.2 Parte cliente JAX-WS 42

3.5 AWS 43 3.5.1 Productos y servicios 43

3.6 Docker 45 3.6.1 Introducción 45 3.6.2 Arquitectura, componente y comandos básicos 45 3.6.3 Otras herramientas del ecosistema Docker 52 3.6.4 Docker en modo Swarm 53

4 Trabajo desarrollado 61 4.1 Fase 1: implementación del servicio PIDS 61

4.1.1 Situación de partida 61 4.1.2 Objetivos 63 4.1.3 Migración del sistema de gestión de la base de datos 63 4.1.4 Transformación de la gestión de sentencias 64 4.1.5 Estructura de paquetes, clases y métodos 73

4.2 Fase 2: PIDS como servicio Web 75 4.2.1 Enfoque descendente / WSDL 75 4.2.2 Implementación del servicio Web 80 4.2.3 Estructura de carpetas para el proyecto y ficheros de despliegue 83 4.2.4 Ant (secuencia de tareas) 85 4.2.5 Cliente del servicio Web 86

4.3 Fase 3: Despliegue en contenedores 89 4.3.1 Descripción de las imágenes Docker 89 4.3.2 Despliegue local 92 4.3.3 Despliegue en un clúster de nodos distribuidos 101

5 Conclusiones 127 5.1 Líneas de mejora 128

Referencias 131

Glosario 134

Page 17: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

xvii

Page 18: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

ÍNDICE DE TABLAS

Tabla 1–1. Norma UNE-EN 13606 5

Tabla 2–1. Clases de conformidad PIDS 12

Tabla 2–2. Especificaciones servicios Web 18

Tabla 2–3. Diferencia mensaje SOAP RCP style y Document style. 21

Tabla 2–4. Tecnologías de virtualización basadas en contenedores 31

Tabla 3–1. Comparativa MyBatis - Hibernate 39

Tabla 3–2. wsimport: equivalencia WSDL / Java 42

Tabla 4–1. Componentes MyBatis 65

Tabla 4–2. Ejemplos descriptivos de traitnames 72

Page 19: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

xix

Page 20: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

ÍNDICE DE FIGURAS

Figura 1-1. Estándares de interoperatividad en el dominio sanitario. 5

Figura 2-1. Modelo de referencia PIDS 10

Figura 2-2. Diagrama de herencia PIDS 11

Figura 2-3. Interacción de un conjunto de servicios Web 16

Figura 2-4. Interacción de un conjunto de servicios Web 19

Figura 2-5. Elementos WSDL 22

Figura 2-6. Diferencias WSDL 1.1 y 2.0 22

Figura 2-7. Monolíticos vs microservicios 24

Figura 2-8. Arquitectura de máquinas virtual frente a contenedores 25

Figura 2-9. PID namespace 27

Figura 2-10. MOUNT namespace 28

Figura 2-11. Responsabilidad entre cliente y proveedor según modalidad de servicio 33

Figura 3-1. Proyecto Metro 40

Figura 3-2. wsimport: equivalencia namespace WSDL / estructura de carpetas 42

Figura 3-3. Arquitectura Docker 46

Figura 3-4. Capas de una imagen 47

Figura 3-5. Tipos de volumenes 49

Figura 3-6. Pila de red 50

Figura 3-7. Redes bridge 51

Figura 3-8. Diferencia redes bridge y overlay 51

Figura 3-9. Comandos Docker 52

Figura 3-10. Descubrimiento de servicios 56

Figura 3-11. Secuencia de balanceo de carga 56

Figura 3-12. Propiedad routing mesh 57

Figura 3-13. Token de anexión al Swarm 57

Figura 4-1. ISO 13606-1:2013: Modelo de referencia 62

Page 21: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

xxi

Figura 4-2. Interfaz pgAdmin III 64

Figura 4-3. Flujo de actividad de los componentes MyBatis 66

Figura 4-4. Estructura del proyecto de servicio Web 83

Figura 4-5. publicación servicio Web 85

Figura 4-6. Cliente NetBeans (1) 87

Figura 4-7. Cliente NetBeans (2) 87

Figura 4-8. Cliente NetBeans (3) 88

Figura 4-9. Cliente NetBeans (4) 88

Figura 4-10. Cliente GUI 88

Figura 4-11. Estructura proyecto Docker 90

Figura 4-12. Estructura proyecto Docker - Compose 92

Figura 4-13. Esquema de contenedores en despliegue local 95

Figura 4-14. Repositorio Docker Hub 100

Figura 4-15. Imágenes en Docker Hub 101

Figura 4-16. Grupo de seguridad 104

Figura 4-17. Grupo de seguridad – servicios publicados 111

Figura 4-18. Visualizer - estado del swarm 112

Figura 4-19. Visualizer - escalado 113

Figura 4-20. Propiedades del volumen dbdata – prueba de resiliencia 114

Figura 4-21. Visualizer - cambio de disponibilidad (drain) de un nodo 115

Figura 4-22. Agentes de escucha del balanceador 116

Figura 4-23. Edición de grupos de seguridad 116

Figura 4-24. Creación de grupo de destino 117

Figura 4-25. Parámetros de la creación del balanceador de carga 118

Figura 4-26. Reglas de balanceo 118

Figura 4-27. Grupos de destino 119

Figura 4-28. Grupos de destino para comunicación segura 122

Figura 4-29. Configuración de agente de escucha seguro 123

Figura 4-30. Esquema del stack deplegado en cloud 123

Figura 5-1. Escenario de partida y final 127

Page 22: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 23: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

1

1 INTRODUCCIÓN

1.1 Contexto

El presente proyecto está contextualizado a nivel macro en la necesidad manifiesta de la transformación digital

del sector de la salud, apoyado en la aplicación fundamental de las tecnologías de la información y la

comunicación (en adelante, TIC).

La incorporación de las TIC a la asistencia sanitaria es un hecho consolidado desde hace mucho tiempo, y se ha

llevado a cabo con el objetivo de mejorar la eficacia, eficiencia y efectividad del sistema de salud, tanto los

relativos a los procesos clínicos como administrativos, en equilibrio con la calidad ofrecida. El uso de sistemas

TIC es un elemento clave para disminuir la fragmentación de los sistemas de salud e incrementar la calidad

asistencial y el grado de cobertura. La actividad propia de los servicios de salud se caracteriza por un

procesamiento masivo de información, motivo por el que las TIC se han convertido en un instrumento clínico.

E incluso, esta sinergia alcanzada con los avances tecnológicos está impulsando una evolución de los servicios

sanitarios que apuntan hacia formas de trabajo cada vez más flexibles y móviles.

A lo largo del documento se hará mención a los aspectos relacionados con la interoperatividad, uso de estándares,

representación de la información clínica, usabilidad, seguridad, privacidad, y confidencialidad que son

características a tener en cuenta para poder abordar la implementación de sistemas sanitarios. Y muy

particularmente se abordará la identificación de personas como prerrequisito clave en el proceso de

implementación.

1.1.1 Transformación digital sanitaria - Historia Clínica Electrónica

En el sector sanitario existen numerosas fuentes de datos heterogéneas que arrojan una gran cantidad de

información relacionada con los pacientes, las enfermedades y los centros sanitarios. Esta información, bien

analizada, resulta de gran utilidad para los profesionales sanitarios. En la práctica, la cantidad de datos e

información que manejan las organizaciones de salud ha obligado a rediseñar los procesos sanitarios basándose

en el uso de las TIC en todos los niveles y para todas las funciones. Contar con un sistema informatizado permite

que los gestores y los profesionales de la salud accedan oportunamente a datos confiables y estructurados,

posibilitando su procesamiento. Sin embargo, para ser efectivos, eficaces y sustentables, los sistemas de salud

deben ser gestionados de forma adecuada y coordinada. Esta gestión es el mecanismo que controla finalmente

el impacto potencial en la calidad asistencial. En un contexto tan complejo como el sanitario incorporar las TIC

a la actividad clínica se convierte en una ardua tarea. La complejidad del ámbito de la salud se debe, entre otros

motivos, a la diversidad de actores involucrados y su heterogeneidad, desde los pacientes hasta las diferentes

especializaciones profesionales e instituciones gubernamentales, cada uno con sus propios intereses, prioridades

y cultura. Todo ello provocó inicialmente que las instituciones sanitarias desarrollaran múltiples sistemas de

información especializados en la resolución de problemas concretos, quedando la información fragmentada en

diversos sistemas independientes. Dado que el acceso a la información útil era parcial, la toma de decisiones se

realizaba con información incompleta, lo que se traduce en potenciales riesgos para los pacientes.

Para garantizar el acceso a una asistencia sanitaria de calidad y segura, es preciso definir una planificación

estratégica que esté coordinada con los diversos actores del sistema de salud. Uno de sus componentes básicos

debería ser centrar en el paciente la transformación digital de los procesos mediante la introducción de las TIC.

Siguiendo este principio, la transformación digital y la implantación de una Historia Clínica Electrónica (HCE)

van de la mano: la historia clínica puede definirse como el repositorio que contiene toda la información relativa

a la salud de un paciente. Por lo tanto, es un instrumento imprescindible para que el profesional de la salud pueda

llevar a cabo su actividad y prestar al paciente la mejor atención posible en cada momento, ya que constituye el

núcleo principal de las fuentes de información de todo el sistema. Abordar la transformación digital entonces,

empezando por tener una Historia Clínica Electrónica, parece ser un paso lógico y necesario, al tiempo que se

convierte en el habilitador necesario para la transformación general de los sistemas sanitarios.

Page 24: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Introducción

2

Entendidos los beneficios y retos de la implantación de un sistema de Historia Clínica Electrónica, abordar este

tipo de proyectos exige cumplir con algunos requisitos indispensables, siendo los más relevantes la identificación

unívoca de las personas, la interoperatividad con otros sistemas mediante la utilización de estándares, la

adecuada representación de la información clínica, el cumplimiento de la normativa legal vigente en materia de

salud, la seguridad y confidencialidad de la información, entre otros.

En los próximos subapartados se hará una breve introducción de al par interoperatividad-estandarización para

reforzar su relevancia en el ámbito de la sanidad.

1.1.1.1 Interoperatividad

La historia de las organizaciones y de los sistemas de información en salud está marcada por la segregación y la

diversidad. Los sistemas y servicios de salud usan tecnologías, formatos y terminologías diferentes, lo que tiende

a aumentar la fragmentación de la información, y por consiguiente repercute en la disgregación de la atención

sanitaria. No obstante, si se quiere definir un proyecto global y consistente, la aproximación de una solución o

aplicación única para todo tampoco funciona. Por tanto, se reconoce la interoperatividad entre sistemas como

uno de los requisitos imprescindibles, concebido como la capacidad para que los sistemas de salud operen de

forma armónica, intercambiando y utilizando al máximo la información disponible. De este modo, la

información es compartida y está accesible desde cualquier punto de la red sanitaria en la que se requiera su

consulta y se garantiza la coherencia y calidad de los datos en todo el sistema, con el consiguiente beneficio para

la continuidad asistencial y la seguridad del paciente.

Inicialmente la interoperatividad se centraba en la comunicación, intercambio y uso de información entre

proveedores de salud y pacientes. Ante el nuevo paradigma de gestión de salud, la interoperatividad debe ampliar

su alcance y garantizar el intercambio de información entre todos los actores que participan en la gestión del

sistema de salud como son las instituciones sanitarias, aseguradoras, prestadores de servicio, agencias

gubernamentales, etc. Trasladando el concepto de interoperatividad a la HCE, el sistema no debe ser entendido

como un silo independiente, sino que requiere información de otros sistemas, tanto de la propia institución como

fuera de ella, por lo que es necesario desarrollarla teniendo en cuenta la posibilidad de intercambio de datos.

Para una interoperatividad completa no es suficiente con usar un estándar para mensajería entre sistemas, se

debe ir más allá del mero transporte de datos y tener estándares que definan la semántica de la información que

luego será transportada. Es por ello que la interoperatividad consta de diferentes niveles:

• Interoperatividad técnica: es la base de la conexión entre sistemas, incluyendo la definición las

interfaces, tanto físicos como lógicos, que permiten que las cargas funcionales puedan intercambiar

información, los mecanismos de interconexión, la presentación de los datos, la accesibilidad u otros

aspectos de naturaleza similar. Se apoya principalmente en formatos estandarizados de intercambio de

información como XML, HTML, JSON o EDI.

• Interoperatividad sintáctica u operativa: centrada en la definición de la sintaxis para la construcción

de los mensajes. Habilita el intercambio, asegurando que la información se transfiera en el formato

correcto, pero sin valorarla. Intercambio de datos, mensajes, documentos mediante el acuerdo de una

estructura sintáctica.

• Interoperatividad semántica: relativa a la interpretación homogénea de los datos intercambiados.

Implica que los sistemas entiendan la información que está procesando mediante el uso de terminologías

y ontologías médicas. Es decir, dos sistemas serán semánticamente interoperables si otorgan el mismo

valor y significado original a la información intercambiada, de forma que cada uno de ellos entiende

por sí mismo lo que el otro extremo le envía. Está dividida en dos clases, la de procesamiento distribuido

y la global. El procesamiento distribuido requiere que los sistemas acuerden previamente qué

información se intercambia, con qué formato, qué protocolo, etc. La interoperatividad semántica global

se basa en conceptos y reglas lógicas para que la información intercambiada pueda ser interpretable de

forma automática por aplicaciones que no intervinieron en su creación.

• Interoperatividad organizativa o de negocio: se sustenta en las reglas de negocio y flujos de trabajo

que regulan la participación de los distintos actores en los procesos colaborativos a nivel de las

organizaciones, con el fin de alcanzar objetivos mutuamente acordados relativos a los servicios que

prestan. En este nivel toma relevancia el conocimiento de los procesos de negocio de la organización.

Page 25: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

3

3

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Está implícito que para lograr los máximos beneficios de la interoperatividad se necesitan mecanismos de

gobierno que permitan establecer un conjunto de normas, procedimiento, políticas, estándares, etc. En definitiva,

la interoperatividad debe estar normalizada. Hablar de interoperatividad no tiene sentido si no se hace dentro de

un marco estandarizado que defina los métodos para llevar a cabo los intercambios de información, y garantice

que la información será correctamente interpretada en diversos sistemas, implementados por distintos

proveedores y en distintas tecnologías.

La prestación integrada de servicios de salud requiere la adopción de estándares sanitarios, de tal forma que

permitan la interoperatividad y el perfeccionamiento de los sistemas de información en salud.

1.1.1.2 Estandarización

Hoy es reconocido por todos los expertos que existe la necesidad de disponer de sistemas distribuidos e

interconectados, y es por esto que es necesario la adopción de estándares en los niveles organizativo, semánticos

y tecnológicos como un elemento estratégico para la interacción y comunicación de los sistemas de Historia

Clínica Electrónica, considerados como el núcleo de la actividad clínica.

Conviene aclarar previamente que los estándares pueden ser abiertos o privados [1]. Los estándares abiertos son

aquellos que pueden ser usados por toda la industria y los desarrolladores sin pago de licencias o derechos de

uso. Por ejemplo, Digital Imaging and Communication in Medicine (DICOM), openEHR y Object Management

Group (OMG). Los estándares privados requieren un registro y/o un pago de derechos de uso y el cumplimiento

de ciertas normas para su implementación.

Por otra parte, los estándares pueden ser reconocidos a nivel internacional, regional o nacional. Siguiendo esta

clasificación se distinguen, por ejemplo, las normas internacionales ISO (International Standard

Organization), las normas del Comité Europeo de Normalización (CEN), y las normas UNE elaboradas por el

organismo de normalización nacional AENOR, a través de diferentes Comités Técnicos de Normalización

(CTN) [21]. Hay procesos que, al tratarse de aspectos técnicos de carácter general reconocidos y no depender

de normativas legales o regulaciones de uso locales, se resuelven convenientemente mediante estándares

internacionales. Sin embargo, existen otros aspectos de fuerte dependencia nacional o local, como la

identificación de personas o de profesionales, que requieren definiciones específicas en cada punto de

implementación.

Tanto para la interoperatividad sintáctica, referida a la estructura de la comunicación entre sistemas, como para

la interoperatividad semántica, referida al entendimiento de la información comunicada, el sector salud ha

desarrollado estándares para varios propósitos. Los esfuerzos de estandarización se concentran en cuatro grandes

áreas:

• Modelos para representa la información en salud, que deben ser capaces de representar la información

en diferentes niveles específicos para poder atender las necesidades tanto clínicas como de gestión, sin

dejar de garantizar que la semántica de los datos capturados sea única.

• Terminologías y modelos de conceptos. Esta es una de las áreas más tradicionales de los estándares en

salud, que incluye nomenclaturas, clasificaciones y ontologías en todas las áreas del conocimiento en

salud, como enfermedades, listas de problemas, diagnósticos, fármacos, técnicas y procedimientos,

determinaciones analíticas y laboratorios, entre otros.

• Comunicación entre sistemas y mensajería, que tiene como objetivo definir los protocolos de

comunicación, y el formato y estructura de elementos de datos utilizados para un eficaz intercambio de

información.

• Seguridad de los datos, que incluye los mecanismos físicos y lógicos que garantizan la confidencialidad,

disponibilidad e integridad de la información, como, por ejemplo, los procesos de autenticación de

usuarios. Los conceptos de firma y certificación digital también están incluidos en esta área.

Page 26: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Introducción

4

Así, por ejemplo, entre los estándares de comunicaciones y mensajería (interoperatividad sintáctica) se

encuentran:

• HL7 V2.X, HL7 V3. Permite el intercambio electrónico de datos demográficos, clínicos y

administrativos, y las comunicaciones entre sistemas de información sanitarios. HL7 v3 está basado

en el modelo de referencia de HL7 (Reference Informative Model o RIM), a partir del cual se

construyen las especificaciones de mensajes relativos a diferentes dominios del entorno de salud,

como contabilidad y facturación, asistencia sanitaria, soporte a las decisiones clínicas, arquitectura

de documento clínico, afirmaciones clínicas, laboratorio, entre otros.

• DICOM. Define la normalización de los registros de imágenes diagnósticas y la forma de comunicarlas.

• X12. Protocolo de comunicación estadounidense aplicado para el intercambio electrónico

multisectorial, entre ellas la salud, de transacciones comerciales, utilizando mensajería EDI y XML.

• CEN/ISO 13606. Para la comunicación de documentos clínicos digitales entre sistemas de Historia

Clínica Electrónica o entre ellos y repositorios de información clínica centralizados. El estándar está

dividido en cinco partes: modelo de referencia (Reference Model o RM), intercambio de arquetipos,

vocabularios y terminología, seguridad y especificación de las interfaces.

Con respecto a estándares de terminología o datos en salud (interoperatividad semántica), algunos de ellos son:

• CIE-10 o Clasificación Internacional de Enfermedades. Es una clasificación estadística de términos

clínicos como diagnósticos, síntomas y procedimientos.

• LOINC. Facilita el intercambio de resultados de pruebas de laboratorio, métricas y otras observaciones

clínicas.

• SNOMED CT. Es un vocabulario clínico normalizado, multilingüe y codificado de gran amplitud,

constituida por conceptos, descripciones y relaciones, que permite la representación del contenido de

los documentos clínicos para su interpretación automática e inequívoca entre sistemas distintos de forma

precisa.

Existen distintas organizaciones desarrolladoras de estándares o SDO (Standards Developing Organizations) en

el campo de la salud para todos sus niveles, entre los que destacan HL7 International, ISO/TC 215, CEN/TC

251, la Sociedad de Sistemas de Información y Gestión en Sanidad (HIMSS), la Asociación Nacional de

Fabricantes Eléctricos (NEMA), la Organización para el Desarrollo de Estándares Internacionales en

Terminología de la Salud (IHTSDO), entre muchas otros.

Esta diversidad de organismos especializados es también un claro reflejo de la fragmentación del sector de la

salud, y la necesidad de unificar criterios en pro de la interoperatividad. Hay en marcha una iniciativa de

armonización, el Joint Initiative Council (JIC), liderada por el Comité ISO (ISO/TC 215) y apoyada por Health

Level Seven International (HL7) y la Comisión Europea (CEN/TC 251), y a la que se van adhiriendo otras

organizaciones, que tiene como objetivo coordinar los esfuerzos en el desarrollo de estándares promoviendo una

línea única de actuación en las áreas donde tenga sentido. Este trabajo debe dar como resultado estándares de

mejor calidad y definidos de manera más rápida.

1.1.1.3 Estándares de la HCE

Los esfuerzos para lograr la interoperatividad semántica en la comunicación (acceder, transferir, modificar o

añadir) de la Historia Clínica Electrónica se concentran en el estándar CEN/ISO EN13606, desarrollado por el

Comité Técnico 251 del Comité Europeo de Normalización (CEN). La aportación más reconocida de la norma

reside en la definición de una estructura de información estable y consistente basado en un modelo dual, que

separa claramente la información (modelo de referencia que contiene las entidades básicas para representar

cualquier información de la HCE) y el conocimiento (modelo de arquetipos que describen semánticamente los

conceptos clínicos como combinaciones estructuradas de las entidades del modelo de referencia).

Por tanto, la adopción del estándar permite que la definición de modelos clínicos o arquetipos puedan ser

Page 27: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

5

5

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

compartidos y reutilizados para alcanzar un proceso de normalización a nivel internacional en el que sea posible

mantener la coordinación clínica.

A nivel nacional está el estándar UNE-EN ISO 13606, asociado al comité CTN 139 que se encarga de la

normalización de las tecnologías de la información y las comunicaciones que sean o puedan ser de aplicación

en el ámbito de la salud y el bienestar en general.

La norma se compone de cinco partes, algunas de las cuales también han sido aprobadas como norma ISO:

Norma Título Comité Técnico / Subcomité

UNE-EN ISO

13606-1:2013

Informática sanitaria. Comunicación de la historia clínica

electrónica. Parte 1: Modelo de referencia. (ISO 13606-

1:2008).

CTN 139 - Tecnologías de la

información y las comunicaciones

para la salud

UNE-EN

13606-2:2007

Informática sanitaria. Comunicación de la historia clínica

electrónica. Parte 2: Arquetipos (Ratificada por AENOR

en octubre de 2007.)

CTN 139 - Tecnologías de la

información y las comunicaciones

para la salud

UNE-EN

13606-3:2008

Informática sanitaria. Comunicación de la historia clínica

electrónica. Parte 3: Arquetipos de referencia y listas de

términos

CTN 139 - Tecnologías de la

información y las comunicaciones

para la salud

UNE-EN

13606-4:2007

Informática sanitaria. Comunicación de la historia clínica

electrónica. Parte 4: Seguridad.

CTN 139/SC 1 - Sistemas de

información e historias clínicas

UNE-EN ISO

13606-5:2010

Informática sanitaria. Comunicación de la historia clínica

electrónica. Parte 5: Especificación de interfaces. (ISO

13606-5:2010)

CTN 139 - Tecnologías de la

información y las comunicaciones

para la salud

Tabla 1–1. Norma UNE-EN 13606

Otros estándares relacionados con aspectos normalizados de la historia clínica electrónica:

• UNE-EN ISO 10781:2015. Informática sanitaria. Modelo funcional de un sistema de historia clínica

electrónica. Publicación 2 (MF HCE) (ISO 10781:2015) (Ratificada por AENOR en octubre de 2015.)

• UNE-CEN ISO/TS 14441:2013. Informática sanitaria. Requisitos de seguridad y privacidad del

sistema de HCE para la evaluación de la conformidad (ISO/TS 14441:2013) (Ratificada por AENOR

en marzo de 2014.)

• UNE-EN ISO 27789:2013. Informática sanitaria. Auditorías de seguimiento de la historia clínica

electrónica (ISO 27789:2013) (Ratificada por AENOR en abril de 2013.)

Figura 1-1. Estándares de interoperatividad en el dominio sanitario.

Page 28: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Introducción

6

1.1.1.4 Identidad unívoca

La identificación inequívoca del paciente es una necesidad esencial de toda actividad en el área de la salud.

Teniendo en cuenta que el objetivo de registrar la información clínica es garantizar que esté accesible durante

todo el proceso asistencial y se pueda consultar en etapas posteriores, un primer riesgo evidente es la posibilidad

de cometer errores en la identificación de las personas que intervengan en el proceso. Por tanto, una primera

condición indispensable al iniciar proyectos de HCE se refiere a normalizar la identificación única de todas las

personas, profesionales, prestadores y proveedores que forman parte del sistema sanitario.

Se da la circunstancia que, teniendo en cuenta la dimensión de los servicios de salud, la complejidad de su

actividad y el elevado número de pacientes y profesionales que se encuentran bajo su cargo, un sistema completo

de salud está compuesto de diversos subsistemas o centros auxiliares, la mayoría de los cuales tratarán datos

personales de los pacientes, que pueden mantener su propio dominio local de identificación de pacientes. Es

precisa una adecuada gestión de los procedimientos de identificación que permita intercambiar información

entre sistemas y evitar que la información se duplique o se encuentre desagregada, sin perjuicio sobre la calidad

de los procesos asistenciales, clínicos y administrativos ni riesgo para la propia seguridad y privacidad de

los pacientes.

1.2 Motivación y objetivos

La evolución de las tecnologías de la e-salud, y por ende de cualquier sistema de información que lo integre,

está marcada por los requisitos de interoperatividad y estandarización. La necesidad de aplicar estos dos

conceptos sobre un sistema de información demográfico en el contexto de un sistema sanitario constituye el eje

central de la motivación que ha conducido al planteamiento del presente proyecto de fin de carrera.

El proyecto arranca desde un servicio de identificación de personas desarrollado en un proyecto previo donde

también se había llegado a definir e implementar sobre una base de datos la estructura de datos basados en

estándares europeos de información sanitaria. No obstante, todo el desarrollo se haría sobre una arquitectura

monolítica y local. Salvado el diseño del modelo de referencia, que no será modificado, la aportación de este

proyecto está enfocada en abordar mejoras sobre el desarrollo inicial y cubrir los requisitos de interoperatividad

técnica conforme a los siguientes objetivos generales:

• Ampliar las capacidades funcionales del sistema de información demográfico de partida para que,

además de identificar de forma unívoca a una persona en base a ciertas características distintivas de la

misma y recabar la información demográfica de una persona a partir de su identificador, también

actualice o borre los atributos registrados de las personas. Adicionalmente, todas estas tareas consultivas

y de actualización deben poder realizarse sobre cualquier tipo de atributo.

• Remodelar la aplicación bajo los principios de bajo acoplamiento y alta cohesión, segregando la lógica

del sistema de la capa de persistencia para dotarla de mayor flexibilidad.

• Permitir una fácil integración operativa con otros sistemas para el intercambio estandarizado de la

información. Teniendo en cuenta la heterogeneidad tecnológica de los sistemas en el ámbito sanitario,

y siendo el sistema de identificación de personas un componente común para todos ellos, es fundamental

envolver el desarrollo objeto del proyecto como un servicio Web, a fin de transformarlo en un sistema

abierto e independiente de la plataforma o lenguaje de los clientes que lo consuman.

• Desplegar el sistema en un entorno que garantice la accesibilidad requerida por la habitual dispersión

geográfica de la red asistencial. En este sentido, también debido a la creciente demanda de servicios de

salud, la tendencia en el sector es aprovechar las ventajas operativas y económicas que ofrece la

tecnología de cómputo en el cloud.

Adicionalmente, el aprovisionamiento del sistema mediante una arquitectura de virtualización basado en

contenedores orquestados dará cobertura a otros objetivos relacionados con proveer características propias de

sistemas productivos y tener un acercamiento a los modelos de desarrollo actuales, tales como:

Page 29: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

7

7

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

• Conseguir un mayor rendimiento y expansión mediante el balanceo de carga y escalabilidad horizontal.

• Establecer una arquitectura que incremente el nivel de tolerancia a fallos.

• Tener una primera aproximación al enfoque basado en microservicios, alejada de la arquitectura

monolítica desde la que parte el proyecto.

• Posibilitar la automatización del despliegue, independientemente de la plataforma o entorno destino, e

integración de manera sencilla en flujos de integración continua.

1.3 Material empleado

Se han utilizado diferentes componentes, librerías software y herramientas para conformar el entorno de trabajo

empleado en la realización del proyecto. Se enumeran a continuación:

Plataforma base: Máquina virtual VirtualBox

Sistema operativo: Ubuntu Linux 16.04 LTS (64-bit)

Prestaciones hardware:

CPU: Intel(R) Core(TM) i7-4510U CPU @ 2.00GHz

RAM: 3GB

Disco: 30GB

Herramientas de desarrollo:

Oracle(R) Java(TM) SE Development Kit 1.8.0_131

Ant 1.9.6

NetBeans IDE 8.2

Librerías adicionales:

Metro (JAX-WS) 2.3.1

Controlador JDBC - PostgreSQL 42.1.4

MyBatis 3.4.5

JAXB2 Basics Plugins 0.11.0

Entorno de trabajo:

Tomcat 8.5.30

PostgreSQL 8.5 + PGAdmin III

Docker 17.09.0-ce

Docker Machine 0.13.0

Docker Compose 1.17.1

Plugin de almacenamiento Docker REX-Ray 0.11.2

Cuenta de Amazon Web Services (AWS)

A lo largo de la memoria se irán aportando detalles de cada elemento y su implicación en el desarrollo del

proyecto.

Page 30: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Introducción

8

1.4 Estructura del documento

Tras la presentación de la motivación y objetivos generales perseguidos en el proyecto, el resto de los capítulos

del proyecto se organizan de la siguiente manera:

Capítulo 2: Estado del arte. En este capítulo se revisa el contexto tecnológico teórico en el que está circunscrito

el proyecto. Se abordan los conceptos tecnológicos generales sobre los que se fundamenta la propuesta de

servicio desarrollada, haciendo un repaso a la evolución que han seguido, los beneficios aportados, algunas

soluciones que los implementan y su posicionamiento en el ámbito del desarrollo software actual.

Capítulo 3: Herramientas. Dedicado a la descripción de las herramientas, servicios y componentes particulares

que han sido relevantes en el desarrollo del proyecto. Se analizan en detalle las características, funcionamiento

y aportación general al proyecto con la idea de ser lo más específico posible en la explicación de las actividades

desempeñadas durante el diseño y construcción del servicio de información demográfico. Para algunas de ellas

se aporta una comparación con otras alternativas directas y la justificación de su selección.

Capítulo 4: Trabajo desarrollado. Capítulo que concentra todo el proceso de desarrollo y configuración de la

solución planteada, a partir de las herramientas tratadas en los capítulos anteriores. Incluye el detalle de las

actividades llevadas a cabo en cada fase de la transformación del servicio de información demográfico, desde la

ampliación funcional de la aplicación hasta su despliegue en un entorno Cloud basado en contenedores, pasando

por el diseño de la misma como servicio Web.

Capítulo 5: Conclusiones y líneas de mejora. Finalmente se concluye con una valoración de los resultados

logrados frente a los objetivos establecidos, y la propuesta de varias opciones de mejora en la línea de

continuidad del proyecto.

Page 31: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

9

2 ESTADO DE LA TÉCNICA

2.1 Servicio de Identificación Demográfico

Una persona a lo largo de su vida será atendida en múltiples centros asistenciales de diferentes organizaciones,

que utilicen diferentes esquemas de identificación, lo que obliga a extender el requisito de la identificación única

de un paciente a dominios de escala regional, nacional e incluso internacional, para habilitar la continuidad

asistencial en un marco de interoperatividad entre sistemas de salud de múltiples instituciones.

No en todos los casos la solución al problema será contar un identificador universal, sujeto a numerosos

problemas de registro reconocidos, y será necesario complementar con criterios alternativos, a partir de

conjuntos de datos demográficos dados, mediante los que resolver las referencias cruzadas de un mismo paciente

y verificar la identidad de una persona. La información más apropiada para identificar a una persona es aquella

cuyos atributos perduren o cambien poco en el tiempo. Se producen situaciones, por ejemplo, en las que el

paciente carece de un documento que acredite su identificador o no lo tiene disponible. Son precisos servicios

de identificación que contemplen tanto el proceso de acreditación de la identidad como la correlación de datos

demográficos.

Los servicios de identificación demográficos nacen con la finalidad de unificar el proceso de asignación e

identificación de las personas en el entorno sanitario, de forma que garantice el acceso de los profesionales

sanitarios a la información sobre los pacientes en términos de calidad y continuidad asistencial. Algunas

especificaciones relacionadas con los servicios de identificación son [2]:

• Person Indentification Service (PIDS) es la especificación del servicio incluido en CORBAmed, grupo

de trabajo perteneciente a la organización internacional OMG (Object Management Group), para la

gestión de identidades basado en un modelo de federación de dominios. Provee de una interfaz con la

que sería posible conectar diferentes modelos de personas pre-existentes, con diferentes formatos de

registro, de manera federada para la interoperatividad entre ellos. De esta forma la especificación

consigue que la mayoría de los sistemas de identificación de personas existentes participen como

componentes de un entorno de integración más amplio.

PIDS es la especificación en la que se basa este proyecto para la implementación de servicio de

identificación demográfico.

• Entity Indentification Service (EIS) es uno de los servicios que componen el proyecto HSSP

(HealthCare Services Specification Project), fruto de un acuerdo conjunto entre HL7 y OMG. Va un

paso más allá del PIDS, proporcionando un conjunto de interfaces de servicios para identificar de

manera unívoca diferentes tipos de entidades, no sólo pacientes individuales, en el ámbito de una

organización de salud o en un conjunto de ellas.

• Perfiles de integración del Integrating the Healthcare Enterprise (IHE), describen casos de uso de

gestión de la información clínica y especifican cómo usar los estándares existentes (HL7, IETF,

DICOM, ISO, etc.) para abordarlos. Es decir, los sistemas interdepartamentales que implementan

perfiles de integración resuelven problemas de interoperatividad. Concretamente, el perfil Patient

Identifier Cross Referencing (PIX) soporta la referencia cruzada de identificadores de pacientes de

varios dominios a partir de un registro maestro de identificadores de pacientes que puede ser consultada

por otras aplicaciones, y el perfil Patient Demographics Query (PDQ) que permite que aplicaciones

consulten un servidor central para recuperar la información demográfica y de visita de un paciente.

• Servicios nacionales basados en identificadores únicos como el Personal Demographics Service (PDS)

del Sistema Nacional de Salud del Reino Unido (NHS).

En el sistema sanitario español, con objeto de disponer de datos normalizados de cada persona, se

emiten dentro de cada Comunidad Autónoma tarjetas sanitarias individuales (TSI). Las tarjetas

sanitarias incorporan una serie de datos básicos comunes, vinculadas a un código de identificación

Page 32: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

10

personal único para cada ciudadano en el Sistema Nacional de Salud. Cada Comunidad Autónoma

dispone de una base de datos de TSI (BDTSI-CA) que se vuelca su información sobre una base de datos

de TSI común (BDTSI-SNS). El Ministerio de Sanidad, Servicios Sociales e Igualdad (MSSSI) es el

responsable de asignar un Código de Identificación Personal para cada persona y vincularlo a otros

códigos personales pueda tener en los distintos territorios del Estado.

2.1.1 PIDS

El servicio de identificación de personas (PIDS) de CORBAmed [3] surge como especificación para abordar la

interoperatividad entre múltiples instituciones, cubriendo la necesidad de identificar pacientes de forma

consistente.

PIDS está diseñado para:

• Soportar de manera simultánea la asignación de identificadores de persona (ID) dentro de un dominio

particular y correlacionar identificadores entre múltiples dominios.

• Agilizar las búsquedas y obtención de coincidencias, independientemente del algoritmo de

coincidencia.

• Apoyar la federación de servicios PIDS independientemente de la topología.

• Proteger la confidencialidad de las personas mediante diversas políticas de confidencialidad y

mecanismos de seguridad.

• Habilitar la interoperatividad entre PIDS que implementen las funcionalidades centrales de la

especificación, y admita la personalización y extensión específicas del servicio.

• Definir diferentes niveles de cumplimiento, según el grado de sofisticación, que van desde consultas

dentro de un único dominio hasta el funcionamiento correlacionando ID en dominios federados grandes.

2.1.1.1 Modelo de Referencia de dominio

El esquema propuesto por CORBAmed PIDS proporciona una solución para soportar la identificación de

pacientes a través de varios organismos de salud. Cada organismo de salud asigna ID que identifican a pacientes

dentro de su dominio local. Fuera de ese sistema u organización dichos ID carecen de significado. PIDS sirve

para federar distintos dominios, generando un lugar en donde los datos de los diferentes dominios se

homogenicen en un único conjunto de datos mínimos. Así, la información sensible de los pacientes permanece

almacenada localmente, con identificadores locales, de forma que solo se relacionan con el identificador del

nivel superior cuando sea necesario transmitirlos.

Figura 2-1. Modelo de referencia PIDS

Page 33: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

11

11

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Con este modelo los pacientes pueden ser identificados en cada punto de atención, sea el caso de centros

auxiliares, laboratorios o emergencia, entre otros. Pero siempre se mantiene la relación con los dominios

superiores que cuentan con datos básicos y son el puente de interconexión entre los dominios inferiores. En la

figura se representa el modelo de referencia para una infraestructura sanitaria compuesto de diversos dominios

de identificación, donde la organización de salud es la encargada de establecer la relación entre ellos.

2.1.1.2 Modelo conceptual

Para caracterizar cualquier atributo demográfico tratado en el servicio, PIDS define una estructura de tipos que

se emplea en todas sus interfaces. Entre los más destacados, el tipo Trait se utiliza para contener cualquier

dato demográfico. Se compone de un campo de nombre, de tipo TraitName, y un campo de valor, que puede

ser de cualquier tipo. Un conjunto de traits se declara con el tipo Profile.

Los restantes tipos de datos se explicarán junto con la descripción de las interfaces que implementa el servicio

de identificación. No obstante, la especificación no restringe ni concreta ningún modelo de datos específico para

representar los atributos demográficos; simplemente se limita a definir la entidad genérica Trait que los

contiene, dejando la posibilidad de usar el modelo de referencia que mejor convenga. Como se ha visto

anteriormente, hay estándares que introducen en sus especificaciones modelos de información con los que

facilitar la integración semántica del sistema. Algunos ejemplos son el RIM de HL7, el RM de openEHR o la

primera parte del CEN/ISO 13606.

2.1.1.3 Interfaces

La especificación provee de interfaces tanto para la gestión de los ID como para el acceso a los datos

demográficos, todas heredadas de un componente, IdentificationComponent, en la que se concentran

las características de las personas emparejadas con un ID.

Figura 2-2. Diagrama de herencia PIDS

Page 34: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

12

Cada interfaz representa una funcionalidad concreta. En función del número de interfaces completas que

implemente el servicio PIDS, lo cual exige cumplir estrictamente con todas las operaciones, atributos,

excepciones y comportamiento esperado para esas interfaces, obtendrá una clase de conformidad diferente con

respecto a la especificación. En la siguiente tabla se resumen los distintos tipos de conformidad junto con las

interfaces que los componen:

Clase Conformidad IdentifyPerson ProfileAccess SequentialAccess IDMgr IdentityAccess CorrelationMgr

Simple PIDS * *

Sequencial Access PIDS * * *

ID Domain Mgr PIDS * * *

Identity Access PIDS * *

Correlation PIDS *

Tabla 2–1. Clases de conformidad PIDS

• Simple PIDS: provee las operaciones básicas para acceder al perfil de un ID y recuperar posibles ID

potenciales que coincidan con algunas características especificadas. Es el tipo de servicio que

implementaría normalmente un sistema auxiliar.

• Sequencial Access PIDS: añade la capacidad de acceder secuencialmente al conjunto de ID.

• ID Domain Mgr PIDS: agrega la capacidad de crear nuevos ID y modificar los estados de los ID

existentes.

• Identity Access PIDS: alternativa al Simple PIDS, proporcionando la misma funcionalidad, pero usa la

interfaz IdentityAccess en lugar de ProfileAccess. De esta forma puede tener diferentes políticas de

acceso para cada ID.

• Correlation PIDS: contiene una única interfaz, que proporciona toda la funcionalidad para cargar y

acceder a los perfiles e ID correlacionados entre los dominios participantes. Se puede combinar con los

otros tipos de conformidad.

Uno de los objetivos de este proyecto será ampliar la implementación de un servicio PIDS de clase "Simple

PIDS", que incluye las interfaces básicas de consulta a la información demográfica. A continuación, se describen

las interfaces que componen el servicio implementado.

Interfaz IdentifyPerson

Esta interfaz proporciona una forma de encontrar los identificadores de personas que concuerdan con un

conjunto de atributos, considerando su relevancia. Tiene un único método, find_candidates, que devuelve

el listado de candidatos que se ajusten con un conjunto de atributos o perfil especificado, por encima de un

umbral de confianza también dado. En la llamada al método se indica también los atributos de los candidatos

potenciales que se quieren conocer. Los parámetros de entrada y salida del método se describen a continuación:

Parámetros de entrada

o profile_selector: conjunto de atributos conocidos de la persona que se busca. Es una

secuencia de elementos de tipo TraitSelector. El TraitSelector es un parámetro

que identifica un atributo de la persona a buscar. Se compone de un Trait y un campo de

peso relativo, a modo de valor de ponderación que tiene la coincidencia del Trait en la

búsqueda de los candidatos. El uso del campo peso no está estandarizando, por lo que

Page 35: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

13

13

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

dependerá de la implementación particular.

o states_of_interest: conjunto de estados (IdState) en los que se deben encontrar los

identificadores de las personas que se buscan.

o confidence_threshold: representa el umbral de confianza. Los candidatos que no

tengan un nivel de coincidencia por encima de este umbral se descartan.

o sequence_max: número máximo de candidatos que se quiere recibir en la llamada. Si el

servicio encuentra más coincidencias, se devuelven en un iterador.

o iterator_max: número máximo de candidatos que se debe devolver en el iterador.

o traits_requested: Atributos que se devolverán para cada candidato. Es una secuencia

de elementos de tipo TraitSpec, que son nombres de atributos para los que el servicio debe

encontrar su valor, junto con algunas características del propio atributo como si es de lectura,

obligatorio o si se puede usar en la búsqueda de personas.

Parámetros de salida

o returned_sequence: secuencia de candidatos devueltos que coinciden parcialmente con la

búsqueda de personas realizada. Contiene el ID de la persona, el campo de confianza de determina

el nivel de coincidencia con el perfil de búsqueda y el conjunto de atributos solicitados en la

llamada.

o returned_iterator: contiene los candidatos que exceden del número máximo requerido en

la consulta.

Interfaz ProfileAccess

Esta es la interfaz principal para acceder a los atributos asociados con un ID. Proporciona los métodos

elementales de un servicio de identificación de personas. Estos métodos son:

• get_traits_known: A partir de un identificador de persona (PersonId) el servicio devuelve un

elemento TraitNameSeq, que contiene todos los nombres de todos los atributos conocidos para dicha

persona.

• get_profile: A partir de un identificador de persona (PersonId) devuelve el conjunto de

atributos, mediante un elemento de tipo Profile, que han sido solicitados en llamada a través de un

elemento de tipo SpecifiedTraits.

• get_profile_list: Es un mecanismo abreviado para obtener perfiles para más de una

identificación a la vez. A partir de una secuencia de ID (PersonIdSeq) devuelve el conjunto de

atributos solicitados los perfiles para cada uno de ellos, mediante una secuencia de elementos de tipo

TaggedProfile. Cada elemento TaggedProfile que incluye un perfil y la identificación

asociada a él.

• get_deactivated_profile_list: Similar al método get_profile_list salvo que

permite obtener perfiles de IDs cuyo estado sea DEACTIVATED (en desuso).

• update_and_clear_traits: Modifica el perfil de un ID. Se pasa como parámetro de entrada

una secuencia de elementos de tipo ProfileUpdate. Este tipo contiene un identificador, el nombre

de los atributos que deben borrarse del perfil y los nuevos valores de los atributos que deben

modificarse.

• get_id_info: Devuelve el estado de cada ID introducido.

Page 36: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

14

2.2 Servicios Web

Se inicia el apartado con una breve revisión de las arquitecturas de software distribuido y su evolución. Será

necesario para comprender los motivos que condicionaron a reformular el servicio de información demográfico

desde el que parte el proyecto, planteado como sistema monolítico ejecutado en un entorno local, para

desarrollarlo como un servicio Web y así satisfacer los requisitos de disponibilidad, interoperatividad y

explotabilidad exigidos por el contexto global del proyecto. 

2.2.1 Arquitectura de software distribuido

A lo largo del tiempo la forma en que se han desarrollado las aplicaciones informáticas ha ido cambiando,

tendiendo siempre hacia un diseño del software cada vez más modular, simplificado y distribuido.  

El software distribuido es aquel en que sus elementos pueden comunicarse entre sí, aunque estén en máquinas

diferentes a través de una red de comunicaciones. Tradicionalmente se parte del protocolo RPC (Remote

Procedure Call) para la comunicación en entornos distribuidos, con el inconveniente de su alto grado de

acoplamiento con la tecnología empleada. Ejemplo de lenguajes que pueden operar en entornos distribuidos

encontramos Java con su RMI (Remote Method Invocation), la tecnología DCOM de Microsoft y CORBA

(Common Object Request Object Architecture) que es un estándar definido por la organización OMG (Object

Management Group). Pero a medida que van creciendo los requisitos de integración entre sistemas de diferentes

tecnologías para el intercambio de información y la cooperación funcional, se va consolidando un enfoque de

diseño orientado en servicios. Las etapas generales en el proceso de diseño de un servicio son:

• Identificación del servicio: consiste en identificar la funcionalidad concreta que va a ser expuesta como

un servicio. Idealmente, la funcionalidad seleccionada debe tener una alta granularidad, sin

dependencias y con potencial para su reutilización, de forma que pueda ser aprovechado de forma

trasversal por varios procesos.

• Diseño: referido a la definición de la interfaz del servicio y así como sus parámetros de entrada y salida.

• Implementación: comprende la selección de la tecnología con la que ejecutar la funcionalidad

seleccionada como servicio.

Otro escenario habitual para el diseño software orientado a servicios se produce bajo la necesidad de

interoperatividad e integración con otros componentes software de sistemas heredados que no pueden ser

reconstruidos.

Así, los principios que caracterizan los servicios frente a los modelos tradicionales de arquitectura distribuida

son, entre otros: 

•  Contrato de descripción del servicio: los contratos definen la especificación de las interfaces del

servicio ofrecido, incluyendo las operaciones permitidas, los tipos y modelo de datos, y los mensajes

necesarios que se intercambiarán para garantizar la estandarización y granularidad de los

servicios. Constituye la base de la arquitectura de software orientada a servicio.

• Bajo acoplamiento: el acoplamiento se refiere al nivel de dependencia entre los sistemas implicados.

Cuanto menor sea el acoplamiento, mayor independencia tendrá el servicio respecto de su

implementación y tecnología empleada. Esta circunstancia hará más sencillo el desarrollo y evolución

de la lógica de negocio del servicio, al no tener impacto sobre los consumidores del servicio por no

haberse alterado el contrato que lo describe.

• Abstracción: está estrechamente relacionada con el concepto de contrato y bajo acoplamiento. Se refiere

a limitar la definición del servicio con la información estrictamente esencial para entender su propósito,

operaciones y mensajes, evitando contener cualquier interpretación técnica de la lógica que la

implementa. Así, el bajo acoplamiento se consigue con niveles adecuados de abstracción en el diseño

del contrato.

• Reusabilidad o multipropósito: la segmentación de la funcionalidad en servicios abstractos permite que

éstos sean reaprovechados por otros servicios y/o sistemas. Cuanto más genérica sea la funcionalidad

Page 37: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

15

15

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

del servicio, mayor será la reusabilidad potencial del mismo. El diseño óptimo de los contratos en la

definición de los servicios abstractos influirá en gran medida sobre su reusabilidad.

Nota: La evolución del modelo orientado a servicios, enfocada en lograr una mayor modularidad de la lógica

de negocio, ha derivado en la aparición del concepto de microservicios. El beneficio directo perseguido por

una arquitectura de microservicios es la agilidad y velocidad para hacer cambios.

Atendiendo a los principios enunciados, se puede entender que las arquitecturas orientadas a servicios estén

estrechamente asociadas a los denominados servicios Web.

Los servicios Web, según la definición de W3C (siglas de World Wide Web Consortium), "[…] es un sistema

de software diseñado para permitir la interoperatividad de máquina a máquina a través de una red". Aquí la

clave está en el concepto de interoperatividad, que permite utilizar los servicios Web para integrar sistemas de

diferentes lenguajes de programación y que se ejecutan en plataformas diferentes, habilitando un mecanismo de

comunicación entre componentes software totalmente independientes a través de la red con plena compatibilidad

y lograr crear sistemas más complejos. Todo esto lo consigue basándose en estándares abiertos, que han sido

adoptados por la industria del software, para la descripción de la interfaz de las operaciones ofrecidas por el

servicio, la creación y codificación de los mensajes de comunicación, y el transporte de los mensajes mediante

protocolos de Internet.

A nivel conceptual, un servicio es una funcionalidad software proporcionada a través de un endpoint accesible

a través de la red. Existen principalmente dos estilos diferentes para el diseño y desarrollo de servicios Web, los

basados en el protocolo SOAP (Simple Object Access Protocol) y los que siguen el estilo de arquitectura

software REST (Representational State Transfer).

Servicios Web SOAP

Los servicios SOAP, o directamente conocidos como Web Services, se basan en el intercambio de

información estructurada para intercomunicarse sobre la red conforme al protocolo SOAP. SOAP es un

protocolo de comunicación basado en XML que describe la arquitectura y el formato de los mensajes a

intercambiar cuando se invoca un servicio Web. Los mensajes SOAP se transmiten usando protocolos

de comunicación como HTTP, SMTP o FTP, aunque el caso más habitual es mediante HTTP.

El diseño de un servicio Web requiere establecer un contrato formal en el que se describa la interfaz que

ofrece el servicio Web. Un documento WSDL (Web Service Description Language) servirá para

construir en XML estos contratos estandarizados, incluyendo información sobre qué funciones están

disponibles en el servicio, cómo invocarlo, dónde encontrarlo, y qué tipos de datos se usan en las

operaciones. Se puede ampliar para especificar otros requerimientos no funcionales como los

relacionados con las transacciones, la seguridad o la coordinación.

Servicios Web RESTful

Los servicios Web RESTful son básicamente servicios Web que implementan la arquitectura software

REST. Sin entrar en detalle, REST constituye un conjunto de principios arquitectónicos que define la

interacción entre distintos componentes. Sustituye el concepto de servicio por el de recurso como el

elemento sobre el que se definen operaciones y que es accesible mediante un identificador único global.

Las restricciones establecidas por la arquitectura REST ya vienen implementadas en el protocolo HTTP,

de ahí a que los servicios Web RESTful estén perfectamente integrados con HTTP, y utilicen sus

métodos y códigos de respuesta para implementar los principios de la arquitectura REST. De esta forma,

se simplifica la comunicación entre aplicaciones ya que los datos se envían directamente sobre el

protocolo HTTP, sin necesidad de emplear un protocolo de comunicaciones como SOAP, ni

definiciones de servicio en forma de fichero WSDL.

Page 38: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

16

Los servicios Web, y particularmente los basados en SOAP, satisfacen de forma intrínseca muchos de los

principios básicos comentados de la arquitectura orientada a servicios. Se logra en gran medida a partir de la

definición abstracta del servicio mediante un lenguaje de descripción de servicios (WSDL) que, a su vez, actúa

como contrato estandarizado de la interfaz de comunicación entre los servicios. Además, mediante WSDL se

consigue un desacoplamiento de la lógica del servicio, de forma que al invocar un servicio Web simplemente

hay que conocer las operaciones disponibles, sin tener detalles sobre la implementación del mismo ni que ello

tenga algún impacto sobre los clientes que lo consume. Atendiendo a la reusabilidad de los servicios Web,

conceptualmente es posible ver los servicios Web como unidades de trabajo que pueden combinarse e interactuar

con otros servicios para reaprovechar las funcionalidades ofrecidas y realizar operaciones complejas.

Todo lo anterior contribuye a potenciar la interoperatividad entre sistemas, promoviendo nuevos escenarios de

colaboración empresarial o integración entre sistemas corporativos, con independencia de la tecnología o

plataforma que los soporten. Ya se comentó en un apartado anterior que uno de los principales retos en la

evolución de la innovación en el campo de la sanidad era la interoperatividad entre organismos, mediante la

estandarización del intercambio de mensajes en un escenario compuesto por sistemas heterogéneos, entre

otros requisitos. Los sistemas sanitarios han encontrado en los servicios Web un importante aliado para

salvar sus requisitos de integración.

Figura 2-3. Interacción de un conjunto de servicios Web

Los siguientes apartados se centrarán en describir las características y funcionalidades de los servicios Web

SOAP, al ser el método seleccionado para exponer la lógica del servicio de información demográfica objeto del

proyecto.

2.2.2 Componentes y estándares de los Servicios Web SOAP

Los Servicios Web involucran una familia de estándares abiertos para describir y suministrar servicios web e

interactuar con ellos, y cuyas especificaciones han sido promovidas por organizaciones o consorcios,

constituidos tanto por proveedores de productos tecnológicos como por organismo de estandarización. Entre

estas organizaciones implicadas en el desarrollo de estándares relacionados con los servicios Web, los más

destacados son W3C, OASIS y WS-I.

W3C (World Wide Web Consortium)

Fundada en 1994 por Tim Berners-Lee, W3C es una comunidad internacional donde diferentes

organizaciones, procedentes de diversos puntos del mundo y de campos muy diferentes, forman parte

del W3C para el desarrollo de estándares Web de alta calidad. La actividad que desempeñan respecto a

los servicios Web es el diseño de la infraestructura, definición de la arquitectura y creación de la

tecnología central de los servicios Web. Entre los estándares que han desarrollado para los servicios

Web se encuentran SOAP y WSDL.

Page 39: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

17

17

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

OASIS (Organization for the Advancement of Structured Information Standards)

OASIS es un consorcio internacional, sin ánimo de lucro, centrado en especificaciones relacionadas con

el comercio electrónico y la seguridad. Sus contribuciones más importantes para los servicios Web son

el servicio de registros UDDI, el lenguaje BPEL para la composición de servicios Web y la

especificación WS-Security sobre seguridad.

WS-I (Web Services Interoperability Organization)

WS-I es el organismo creado para fomentar la interoperatividad entre diferentes implementaciones de

Servicios Web. Publicó el WS-I Basic Profile, una guía con las mejores prácticas sobre cómo deben

usarse correctamente los estándares, como XML, SOAP, WSDL o UDDI, para ayudar a la comunidad

a desarrollar e implementar servicios web interoperables. Pasó a formar parte de OASIS y finaliza su

actividad en diciembre de 2017.

Más adelante se entrará en detalle a describir los estándares y protocolos que, como tales, conforman los

fundamentos para el desarrollo de los servicios Web, independientemente de la plataforma donde se construyan

dichos servicios. Estos estándares se han ido complementando posteriormente con la aparición de

especificaciones que extienden a SOAP con la intención de cubrir las carencias iniciales de la especificación de

los servicios web, y dotarles de flexibilidad y modularidad en el ámbito de áreas como la calidad del servicio, la

seguridad, el procesamiento distribuido de transacciones, etc. Algunas de las extensiones, denominadas WS-*,

son las siguientes:

• Attachments – Permite incluir documentos no XML, como archivos binarios o imágenes. 

• Routing/Intermediaries – Relacionadas al proceso de enviar mensajes SOAP a través de intermediarios.

Permite agregar varios servicios Web y ofrecerlos como parte del paquete, incrementando la

escalabilidad de los servicios.

• WS-Security – Proporciona un marco de seguridad para la comunicación. Así, el envelope SOAP

soporta integridad del mensaje, confidencialidad y autenticación. Describe el uso de certificados X.509,

firmas digitales, tockets Kerberos, etc.

• WS-Policy – Es una ampliación del WS-Security. Permite configurar más detalle cómo y quién puede

usar un servicio Web.

• WS-Addressing – Define cómo se debe representar la dirección e instancia concreta del servicio en un

mensaje SOAP. Necesario para declarar servicio stateful.

• WS-ReliableMessaging – Establece las normas para el intercambio fiable de mensajes.

• Quality of Services – QoS es una medida de la calidad del servicio; con esta extensión es posible

caracterizar el funcionamiento del servicio.

• Context/Privacy – Relacionada con la WS-Security, hace referencia a guardar el contexto y la

privacidad del entorno de los usuarios.

No obstante, estas extensiones no serán objeto del estudio en el proyecto y serán propuestos como puntos de

mejora futuros, especialmente la especificación WS-Security relativa a la implementación de la seguridad en el

intercambio de mensajes para garantizar su integridad y confidencialidad, y la autenticación de los extremos.

De forma resumida, XML es el metalenguaje con el que se construyen los demás estándares, SOAP es la

implementación de los mensajes en los servicios web, WSDL servirá para construir contratos estandarizados

con soporte de XML Schema, y UDDI registrará el WSDL del servicio para que sea publicado y localizable.

Page 40: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

18

Protocolo

Capa Descripción

HTTP Hypertext

Transfer

Protocol

Transporte del

servicio

Responsable de transportar los mensajes entre las aplicaciones o

servicios. En realidad, puede usarse cualquiera de los protocolos

estándar de Internet (SMTP, FTP, POP), siendo el más común el

protocolo HTTP.

SOAP Simple Object Access Protocol

X

M

L

Mensajería XML

Detalla la forma en que se construyen los mensajes en XML que

van a ser intercambiados durante el proceso de comunicación

entre servicios. Las principales características del protocolo son la

extensibilidad (se pueden ampliar fácilmente con nuevas

especificaciones), neutralidad (puede usarse con cualquier

protocolo de transporte) y la independencia (puede usar

independientemente del lenguaje de programación o arquitectura

usada)

WSDL Web Service

Description Language

Descripción del

servicio

Define de forma estándar, utilizando XML Schema, el modo de

describir la interfaz pública de un determinado servicio,

incluyendo desde la forma que deben tener de los mensajes hasta

la localización a la que deben ser enviados.

UDDI Universal

Description

Discovery and Integration

Publicación y

localización

Especifica la forma de publicar servicios Web en un registro y

cómo puede consultarse para descubrir servicios que estuvieran

disponibles.

Inicialmente estaba pensado para ser un registro global, pero este

objetivo no llegó a consolidarse. Se emplea como registro interno

de servicios y descripción de servicios.

Como alternativa o complemento a UDDI, la especificación WSIL

(Web Service Inspection Language) propone un enfoque

alternativo para el descubrimiento de servicios distribuidos, sin

necesidad de consultar a un registro centralizado, preguntando

directamente al proveedor de servicios sobre los servicios que

proporciona.

Tabla 2–2. Especificaciones servicios Web

2.2.2.1 XML

XML (Extensible Markup Language) es un metalenguaje simple de marcas (etiquetas), desarrollado por W3C,

cuya finalidad es la de establecer la estructura de modelos de información en un ámbito general. En el contexto

de los servicios Web, con XML se define el formato estándar para estructurar los datos intercambiados, de

acuerdo al protocolo SOAP, y establece el formato y la estructura de los documentos WSDL que describen los

servicios.

2.2.2.2 Mensaje SOAP

Un mensaje SOAP es un documento XML ordinario que contienen los siguientes elementos:

• Envoltorio ("envelope"): es el elemento raíz de un mensaje SOAP y es obligatorio. Este elemento define

el documento XML como un mensaje SOAP, marcando su comienzo y final. Debe estar vinculado al

namespace declarado con valor http://www.w3.org/2003/05/soap-envelope/. Si se

usase otro namespace diferente, se generaría un error y el mensaje sería descartado. Incluye dos sub-

elementos, la cabecera ("header") y el cuerpo ("body") del mensaje.

• Cabecera ("header"): es un elemento opcional que tiene la finalidad de proporcionar información

específica de la aplicación acerca del mensaje en sí mismo. Se puede componer de varios sub-elementos

o bloques de cabecera que aportan la información de control adicional procesada por nodos intermedios

SOAP a lo largo del flujo de mensajes. Se entiende por nodo SOAP cualquier aplicación que procese

los mensajes SOAP. Los bloques de cabecera son el medio para ampliar el mensaje con nuevas

funcionalidades (seguridad, enrutamiento, coordinación, etc.).

Page 41: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

19

19

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

• Cuerpo ("body"): es el elemento obligatorio que contiene los datos propios de la aplicación ("carga útil")

que se intercambian en el mensaje SOAP y dirigida al destinatario final del mensaje. Normalmente

serán datos en formato XML. SOAP define un elemento hijo para el cuerpo, el elemento fault, que se

utiliza para notificar errores en el procesamiento del mensaje, e incluye información específica del error,

como un código predefinido, una descripción, y la dirección del nodo que ha generado el error. Otros

elementos del cuerpo los define el servicio web que los utiliza.

Cuando sea necesario enviar en el mensaje datos que no son XML, será necesario recurrir a la especificación de

mensajes SwA (SOAP with Attachments) o MTOM (Message Transmission Optimization Mechanism). De esta

forma será posible enviar cualquier tipo de contenido junto al mensaje SOAP.

<?xml version = "1.0"?>

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"

soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">

<soap:Header>

</soap:Header>

<soap:Body>

<soap:Fault>

</soap:Fault>

</soap:Body>

</soap:Envelope>

La especificación SOAP define la estructura de los mensajes, pero no la forma en que se estos se intercambian.

Para ello se usan los llamados "enlaces SOAP" ("SOAP bindings"), que permite especificar cómo debe

transmitirse un mensaje SOAP utilizando un protocolo determinado para después enviar el mensaje con las

cabeceras propias del protocolo. La mayoría de las implementaciones de SOAP proporcionan enlaces para los

protocolos de comunicación más comunes, como HTTP o SMTP; sin embargo, HTTP es el único protocolo

estandarizado para SOAP, lo que garantiza que esté soportado prácticamente por todas las implementaciones de

SOAP.

Una solicitud HTTP SOAP especifica al menos dos encabezados HTTP:

• Content-Type: define el tipo MIME del mensaje y la codificación (opcional) usado para el cuerpo

del mensaje.

• Content-Length: especifica el número de bytes en el cuerpo del mensaje.

Figura 2-4. Interacción de un conjunto de servicios Web

Page 42: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

20

2.2.2.3 XML Schema

Como se introdujo antes, un esquema XML (XML schema) describe la estructura de un documento XML,

semántica, y restricciones sobre su contenido, permitiendo su validación. A este lenguaje también se le conoce

como XSD (XML Schema Definition). Establece los requisitos estructurales como qué elementos, qué tipo de

datos, qué atributos, cuántas veces se repiten, etc. Muchos de los formatos XML estandarizados están definidos

por un esquema XML.

Es una alternativa a los esquemas DTD (Document Type Definition) pero con mayores ventajas al estar formados

en XML:

• Es posible confirmar que está bien formado conforme a las reglas sintácticas de XML.

• Soporta tipos de datos predeterminados para elementos y atributos que pueden combinar o restringir

para crear nuevos patrones de datos.

• Son extensibles y se pueden reutilizar en otros esquemas gracias a los espacios de nombres

("namespaces"), que evitan los conflictos de nombres entre elementos y atributos que tienen el mismo

nombre, pero diferentes funciones u orígenes.

Una vez explicado el uso de los esquemas XML, será más sencillo entender la estructura de los ficheros WSDL.

2.2.2.4 WSDL

WSDL es un leguaje basado en XML para la descripción de la interfaz funcional de un servicio Web. En

términos generales, un documento WSDL especifica los detalles de las operaciones, los mecanismos de

interacción, incluyendo los tipos y formatos de los datos de envío y devolución, y la localización del servicio.

El hecho de que esté estandarizado y escrito en XML permite que pueda ser procesado por máquinas (machine

readable) hasta tal punto que, a partir de la definición WSDL del servicio Web, se generen automáticamente los

componentes de código adicionales para la implementación del servicio y de los propios clientes.

La estructura del documento WSDL se puede separar en dos secciones diferenciadas, relacionadas con la

descripción abstracta del servicio y la descripción concreta. La parte abstracta describe la interfaz y mensajes

del servicio Web con detalle, es decir, los elementos del servicio que no guardan relación con ninguna tecnología

en particular y que no serían susceptibles de modificación si se produjera un cambio en la tecnología del servicio;

mientras que la parte concreta sí especifica elementos asociados a un tipo de tecnología en concreto, como el

protocolo de comunicación empleado o la localización del servicio.

A continuación, se verán con más detalle cada uno de los elementos WSDL implicados en cada parte del

documento:

Descripción abstracta:

Elemento <definitions>: es el elemento raíz del documento WSDL. Por lo general, contiene un

conjunto de declaraciones de espacio de nombres que se utilizan en todo el archivo WSDL.

Elemento <types>: definen los tipos de datos que se utilizan en los mensajes que se van a intercambiar.

Es posible definir los tipos de datos directamente dentro del elemento o importando el fichero XSD

donde se hizo.

Elemento <message>: define de forma abstracta los datos intercambiados en las solicitudes y

respuestas realizadas entre el proveedor y consumidor del servicio Web. Los mensajes contendrán partes

(<part>) relacionado con los tipos de datos definidos en el elemento <types>, o se puede indicar

directamente un tipo de dato si es de tipo simple predefinido.

Elemento <portType>: contiene el conjunto de operaciones abstractas permitidas por el servicio

Web, semejante a la definición de una interfaz (término empleado en WSDL 2.0). Cada operación

define los mensajes de entrada (input) y salida (output) que están implicados. En función del orden y

la combinación de mensajes de entrada y salida en la operación, se pueden identificar cuatro patrones

de intercambio (MEP): one-way (la operación recibe un mensaje input pero no devuelve respuesta

Page 43: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

21

21

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

output), request-response (la operación recibe una petición input y devuelve una respuesta output),

solicit-response (la operación puede enviar una petición output y esperar un respuesta input), y

notification (la operación manda un mensaje outpu y no espera por una respuesta output).

Descripción concreta:

Elemento <binding>: especifica los protocolos de comunicación que deben usarse y el formato de los

datos para las operaciones de cada <portType>. Es decir, indica cómo acceder al servicio Web. En el

caso de un binding de SOAP/HTTP, el binding incluirá toda la información necesaria sobre cómo se va

a estructurar la carga útil de los mensajes SOAP que se intercambien, mediante los atributos estilo (style)

y uso (use), de forma que no haya error de interpretación y se puedan procesar los mensajes

automáticamente.

En función de la combinación de los atributos style/use, existen tres mecanismos para la codificación

de la carga útil de los mensajes SOAP: RPC/encoded (no recomendado por WS-I), RPC/literal y

Document/literal, siendo ésta última la recomendada para la mayoría de los casos, principalmente

porque permite validar el documento enviado en el mensaje SOAP contra un esquema.

• RCP style: especifica que el <soap:body> contiene un elemento con el nombre de la operación

del servicio Web invocado. Este elemento contiene una entrada por cada parámetro de la

operación, o con el valor devuelto para los mensajes de respuesta. Es decir, el contenido de

<soap:body> es descrito por el WSDL (de la operación y el nombre del componente) y, a

continuación, por esquema XML.

• Document style: las partes del mensaje se colocan bajo <soap:body>. El contenido de <soap:

body> está descrito por el esquema XML de la sección <types> del documento WSDL. La

aplicación del servidor es responsable de mapear los objetos del servidor (parámetros, llamadas

a métodos, etc.) y los valores de los documentos XML.

public void myMethod(int x, float y);

<types>

    <schema>

        <element name="xElement" type="xsd:int"/>

        <element name="yElement" type="xsd:float"/>     </schema> </types>

  <message name="myMethodRequest">

    <part name="x" element="xElement"/>

    <part name="y" element="yElement"/> </message>

<message name="empty"/>

  <portType name="PT">

    <operation name="myMethod">

        <input message="myMethodRequest"/>

        <output message="empty"/>     </operation> </portType>

<binding .../> 

Mensaje SOAP RPC/literal

<soap:envelope>

    <soap:body>

        <myMethod>

            <x>5</x>             <y>5.0</y>

        </myMethod>

    </soap:body> </soap:envelope>

Mensaje SOAP Document/literal

<soap:envelope>

    <soap:body>

        <xElement>5</xElement>         <yElement>5.0</yElement>

    </soap:body> </soap:envelope>

Tabla 2–3. Diferencia mensaje SOAP RCP style y Document style.

Elemento <service>: contiene una colección de puertos o ports. Cada puerto especifica el punto de

acceso o dirección de red (endpoint) vinculado a un binding desde el que se puede acceder al servicio

Web.

Page 44: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

22

Figura 2-5. Elementos WSDL

De forma resumida, un servicio (service) se accede mediante un port asociado a un binding particular. Este

binding es una implementación de un portType, que describe las operaciones (operation) del servicio. Estas

operaciones del portType se componen de mensajes (message) que intercambian datos XML definidos por los

types.

La estructura documentada es la referida a la versión WSDL 1.1, ya que es la que se utiliza en el desarrollo del

proyecto. Existe una versión más actual, WSDL 2.0, que plantea algunos cambios menores semánticos y otros

de nomenclatura y estructurales, con el objetivo de conseguir un mayor entendimiento. Las principales

diferencias de estructura de WSDL 2.0 con respecto a WSDL 1.1 son:

• Reemplaza el elemento definitions por description

• Integra el elemento message en el elemento types.

• Reemplaza el elemento portType por interface

• Reemplaza el elemento port por endpoint

Figura 2-6. Diferencias WSDL 1.1 y 2.0

Page 45: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

23

23

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Sin embargo, la versión WSDL 2.0 no ha tenido una adopción formal y hasta la fecha no se ha convertido en

estándar. Este es el principal motivo por el que no está soportada por muchas de las herramientas o

implementaciones de los servicios Web como puede ser SOAPUI, CXF o APIs de JAVA.

Se ha mencionado que el formato estándar de WSDL basado en XML para la descripción de un servicio Web

lo convierte en un componente que puede ser procesado automáticamente. Esto ha propiciado que la mayoría

de los entornos de desarrollo, framework de aplicaciones o APIs de programación relacionados con los servicios

Web introduzcan herramientas que facilitan la programación de dichos servicios. El desarrollo de Servicios Web

sería una tarea altamente tediosa si hubiera que desarrollar el código para interpretar los mensajes SOAP de

entrada, y generar manualmente el mensaje de respuesta. Atendiendo al modelo de programación que se

mantenga, se hablan de dos enfoques en el diseño de servicios Web:

• Enfoque ascendente (bottom-up) o code-first, con el que se crea el correspondiente documento WSDL

a partir del código fuente del servicio ya existente.

• Enfoque descendente (top-down) o contract-first, para la generación de las interfaces de código

necesarias para invocar un servicio Web a partir del documento WSDL que lo describe.

El método empleado dependerá de varios criterios como la complejidad o la permutabilidad del servicio, el

entorno donde se vaya a consumir, etc. Por norma general, el enfoque contract-first es el que ofrece una mayor

eficacia dado que el diseño estándar definido en el contrato es incorporado a la lógica de negocio del servicio,

es decir, exige un planteamiento previo y definición iniciales, tanto de los servicios, como de los datos que van

a formar parte del mismo. Además, el desacoplamiento con la lógica interna de la aplicación le otorga robustez

frente a modificaciones, y asegura la reusabilidad, un mejor rendimiento y un sencillo control del versionado.

2.3 Contenedores

En los últimos años se están introduciendo dos nuevas innovaciones tecnológicas en dos ámbitos tecnológicos

muy distintos, como son la arquitectura software y la infraestructura virtualizada, pero cuya tendencia y

evolución parecen ir de la mano: los microservicios y contenedores. 

Sin entrar en un detalle técnico, la arquitectura basada en microservicios pretende solucionar problemáticas

específicas de las aplicaciones monolíticas, en las que toda la funcionalidad está contenida en una gran y única

pieza de software, dificultando la escalabilidad y el mantenimiento de la aplicación. Esto implica que todo el

bloque debe realizarse sobre la misma tecnología, se ejecuta sobre un mismo proceso y, muy especialmente, que

cualquier cambio requerido supone un redespliegue global de la aplicación en su conjunto ya que podría

potencialmente afectar otras partes. En estos casos, la complejidad de la situación es en la mayoría de las

ocasiones proporcional al tamaño del equipo de desarrollo.

El enfoque que subyace tras los microservicios es la división de la aplicación en pequeños módulos

autocontenidos y que ofrecen una determinada funcionalidad, siguiendo la regla de mínimo acoplamiento y

máxima cohesión [4]. Esta división permite la evolución de cada funcionalidad por separado, habilitando a la

aplicación crecer y decrecer ágilmente en función de la demanda o necesidades de negocio, tanto en escalado

horizontal como en funcionalidad de dichos bloques/servicios, y reduciendo la complejidad del sistema, ya que

cada microservicio se ocupa de resolver un problema concreto.

La siguiente figura representa la comparación entre los enfoques de desarrollo que se vienen discutiendo: 

Page 46: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

24

Figura 2-7. Monolíticos vs microservicios

En cierto modo, los microservicios son la evolución natural de las arquitecturas orientadas a servicios (SOA, de

sus siglas en inglés Service Oriented Architecture). 

No obstante, este cambio de paradigma introducido por los microservicios abre la necesidad de resolver nuevos

desafíos relativos a la administración de los servicios y gobernanza, transaccionalidad en las operaciones,

consistencia de los datos, control de versiones, estrategia de pruebas, gestión de la seguridad, entre otras. Es por

ello que, para solucionar los retos de arquitectura planteados, aparte de la funcionalidad principal del

microservicio, necesitaremos incluir en nuestro sistema componentes operacionales específicos que posibiliten

una correcta implementación de la arquitectura, como mecanismos de descubrimiento de servicios,

balanceadores de carga, centralización de logs, monitorización del estado de salud de los nodos y servicios, etc.

Con todo el esquema arquitectónico de referencia aclarado, el siguiente paso es concretar su modelo de

despliegue, referido como el modo en que vamos a organizar y gestionar los despliegues de los microservicios,

así como a las tecnologías disponibles para tal fin. En este punto es donde la virtualización de contenedores ha

tomado especial relevancia frente a las virtualizaciones convencionales de máquinas, basado en la emulación de

componentes de hardware para poder utilizar varios servidores virtuales con su propio sistema operativo.

La virtualización basada en contenedores es una aproximación a la virtualización en la cual la capa de

virtualización se ejecuta como una aplicación en el sistema operativo del equipo anfitrión. En este enfoque, sólo

se ejecuta un único núcleo o kernel del sistema operativo, el correspondiente al host anfitrión, que se comparte

de forma aislada con los entornos virtuales invitados o "guest" ejecutados sobre el mismo, denominados

contenedores. 

El contenedor, en su concepción más básica, opera como un proceso para el sistema operativo y empaqueta una

aplicación junto con todas las dependencias que necesita para ejecutarse. Esta aplicación tiene una vista aislada

del sistema de archivos y de otros recursos que ha provisionado el host del contenedor para él, y utiliza

indirectamente el kernel del sistema operativo principal para ejecutarse [5]. El aislamiento lógico entre

contenedores se consigue mediante diferentes medidas técnicas que básicamente consisten en asignar espacios

de nombres o namespaces distintos a cada sistema invitado. Inicialmente los espacios de nombres eran un sector

de tecnología reservado a Linux, sin embargo, en los últimos dos años, Microsoft ha hecho un importante

esfuerzo, inversión y alianzas para el desarrollo de la tecnología de contenedores de Windows [6]. 

1) Las aplicaciones monolíticas se dividen en

capas funcionales, como Web, negocios y datos.

2) Para escalar aplicaciones monolíticas, es

preciso clonarlas en varios servidores.

3) Las aplicaciones de microservicios separan las

funciones en servicios más pequeños

independientes.

4) Este enfoque de microservicios se escala

horizontalmente mediante la implementación de

cada servicio de manera independiente, con la

creación de instancias de estos servicios en

servidores.

Page 47: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

25

25

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

La tecnología de contenedores se alinea perfectamente con el desarrollo ágil, independiente y escalable que

demanda la arquitectura de microservicios. No obstante, del mismo modo que sería completamente posible

construir una aplicación siguiendo un enfoque de microservicios sin usar contenedores, es posible construir una

aplicación mucho más tradicional dentro de un contenedor, lo que puede tener sentido cuando se quiere

aprovechar las capacidades de orquestación de contenedores que se cerán a continuación.

2.3.1 Arquitectura de contenedores: similitudes y diferencias con máquinas virtuales

Aunque a priori el concepto de contenedores pueda confundirse con el de máquina virtual por las similitudes

que comparten, revisando las diferencias más destacadas entre ambas tecnologías de virtualización será posible

entender las principales ventajas e inconvenientes de la virtualización de contenedores, así como los escenarios

en los que encaja mejor un modelo de virtualización u otro. 

Para una mayor comprensión, en el siguiente diagrama se compara gráficamente el modelo de capas de las

arquitecturas de máquina virtual y de contenedor. 

Figura 2-8. Arquitectura de máquinas virtual frente a contenedores

Como se deduce del diagrama anterior, la principal diferencia entre máquina virtual y contenedor radica en la

forma en la que cada modelo de virtualización utiliza los recursos de la máquina [7]. Mientras que la máquina

virtual requiere de un hipervisor, también conocido como monitor de máquina virtual, sobre el que montar su

propio sistema operativo completo, el motor de contenedores usa el sistema operativo subyacente del host. 

Así, las máquinas virtuales comparten los recursos hardware y el hipervisor se ocupa de la asignación de dichos

recursos a cada máquina, mientras que los contenedores comparten sistema operativo, ejecutándose

directamente sobre el kernel como un proceso más, sin necesidad de duplicar librerías ni aplicaciones en cada

contenedor. 

Desde este punto de partida, surgen el resto de diferencias entre ambas tecnologías. Se compararán en términos

de rapidez, portabilidad, y seguridad. 

Rapidez: 

Cada máquina virtual arranca y ejecuta su propia instancia completa del sistema operativo que utilice,

labor supervisada por la capa de hipervisor, con el consecuente aumento en el consumo de recursos

hardware, y de la dedicación en la puesta en marcha y mantenimiento del sistema operativo. Esta

sobrecarga no se produce en el caso de los contenedores, que van a consumir muchos menos recursos

del host anfitrión. En términos prácticos, esto puede significar que se pueden poner dos o tres veces más

aplicaciones en un único servidor con los contenedores que con las máquinas virtuales.

También derivado del punto anterior, los tiempos de inicio, apagado y ejecución son menores en

contenedores, quedando reducido a la ejecución de un nuevo proceso para el sistema operativo, mientras

que una máquina virtual requiere del arranque normal de un sistema operativo con todos sus

componentes y servicios habituales.

Page 48: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

26

Portabilidad: 

Los contenedores "empaquetan" sus propias dependencias, que incluyen tanto los recursos software

como hardware. Así pues, la virtualización de contenedores no exige de una máquina física para poder

ejecutarse.  El software necesario para la virtualización de contenedores puede ejecutarse sin problemas,

tanto sobre un servidor virtual como físico, mientras que un sistema de virtualización clásico necesita

de un equipo físico anfitrión y un hipervisor para realizar el control.  

Por ejemplo, se puede aprovechar la alta capacidad de portabilidad de los contenedores en el ciclo de

vida para el desarrollo de software, ya que propicia el despliegue ágil de aplicaciones tanto en entornos

de desarrollo como de producción, simplificando a desarrolladores y administradores de sistemas las

pruebas y adaptaciones a cambios de hardware desde el entorno de prueba al de producción. Al contrario

que con máquinas virtuales con las que no sería tan fácilmente posible conseguir una estandarización

del entorno donde funcionará nuestra aplicación.

Por otro lado, si bien usar el mismo sistema operativo hace que los contenedores no deban preocuparse

por las dependencias, una vez las aplicaciones se estén ejecutando adecuadamente, también los limita

en cierta medida. Con las máquinas virtuales no importa que hipervisor esté utilizando (KVM, Hyper-

V, Xen o cualquier otro), pueden utilizar cualquier sistema operativo.

Seguridad: 

Una de las ventajas de la utilización de máquinas virtuales es la abstracción a nivel de hardware que se

traduce en kernels individuales para cada máquina. Todo ello redunda en un mayor nivel de aislamiento

y seguridad, al quedar reducida la superficie de ataque al hipervisor. 

Los contenedores proporcionan mecanismos que posibilitan el aislamiento. Sin embargo, en caso de

producirse una brecha de seguridad que ponga en riesgo el kernel, un atacante podría comprometer uno

de contenedores y dejar expuestos al resto de contenedores o al propio host anfitrión en que se ejecutan

y con los que comparte el kernel. Además, el riesgo será proporcional a la densidad de contenedores

alojados en el host anfitrión.

Así pues, los contenedores no son tan herméticos como las máquinas virtuales con sistema operativo

propio. Y, aunque en el primer caso un ataque al hipervisor pudiera ocasionar graves daños, al ser menos

complejos, no lograrían tanto alcance como en el caso de un kernel.

Nota: Un ejemplo de vulnerabilidades que pueden comprometer el kernel del sistema son Spectre y Meltdown

(CVE-2017-5753, CVE-2017-5715 y CVE-2017-5754). Concretamente, la vulnerabilidad Meltdown es una

vulnerabilidad de seguridad en el hardware que afecta a microprocesadores de Intel, ARM y AMD, y que

permitiría que un proceso maligno pueda leer de la memoria que pertenece al kernel, aún sin contar con

autorización para hacerlo. Esto significa que Meltdown puede eludir el aislamiento entre los contenedores que

comparten el kernel comprometido y, por lo tanto, exponer los datos de todos los demás contenedores en el

mismo host físico. 

Nota: Microsoft ha conseguido proporcionar dos tipos de contenedores que difieren en el nivel de aislamiento

que ofrecen. En este sentido, los contenedores de Hyper-V ofrecerán mayor aislamiento mediante una

virtualización optimizada y el sistema operativo Windows Server que separa los contenedores entre sí y del

sistema operativo host, en perjuicio del rendimiento y eficiencia en tiempo de ejecución. Están especialmente

diseñados para entornos multiinquilinos (con requisitos para el hospedaje de código no seguro), entre los que

se incluyen las aplicaciones de SaaS y el hospedaje de procesos. 

Page 49: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

27

27

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

2.3.2 Escenarios de uso habituales

Las virtudes que se han puesto de manifiesto de los contenedores frente a las máquinas virtuales no significan

que vayan a reemplazarlas o apartarlas por completo del panorama tecnológico. Los expertos coinciden en que

ambos sistemas de virtualización aportan valores distintivos, y la decisión de usar una u otra tecnología vendrá

fuertemente determinada por el alcance y requisitos que tenga nuestro servicio. De hecho, no es extraño hablar

de soluciones híbridas donde aparezcan ambos conceptos, como el uso de contenedores dentro de máquinas

virtuales, evitando por ejemplo algunos de los problemas de seguridad implícitos en los contenedores que se

comentaron anteriormente. 

Se observa que las máquinas virtuales son preferibles en entornos estables, consolidados y con aplicaciones

heterogéneas. Sin embargo, será más factible encontrar contenedores en alguno de los siguientes casos:

• Entornos de integración continua, cuando el paso de desarrollo a producción en un proyecto sea lo más

a menudo posible, para así poder detectar fallos cuanto antes. 

• En el despliegue de aplicaciones dónde sea necesaria una arquitectura de microservicios, de alta carga,

que requieran un alto grado de replicación y con capacidad de dimensionar los servicios de forma rápida

y automatizada.

• Para la creación de un entorno operativo consistente, en el que una aplicación pueda ser trasladada de

un ambiente a otro (desarrollo, prueba, producción) con mínimo o nulo impacto.

2.3.3 Componentes del kernel

Los espacios de nombre o namespaces, junto con los cgroups, constituyen la base de los contenedores Linux:

• Los grupos de control o cgroups son un excelente mecanismo para controlar la asignación de recursos

hardware, limitando el impacto en el sistema. Para ello se definen jerarquías en árbol en las que se

agrupan los procesos del sistema apoyándose en una ruta del sistema de ficheros, normalmente ubicado

en /sys/fs/cgroup o /cgroup.

• Los namespaces son una funcionalidad del kernel, soportada a partir de la versión 2.6.23, que permite

crear una abstracción de recursos del sistema (identificadores de procesos, nombres de máquina,

identificadores de usuario, recursos de red, etc.) y los vincula solo a los procesos que están contenidos

dentro del mismo espacio de nombres, garantizando un espacio independiente y aislado entre los

mismos [8].

Existen 7 tipos diferentes de namespaces, relacionados con distintos aspectos del sistema:

o NETWORK namespace. Aísla los entornos a nivel de red. Así, cada namespace de red tendrá sus

propios interfaces de red, direcciones de red, tablas de enrutamiento, puertos de red, etc.

o PID namespace. Aísla el espacio de identificadores de proceso. Un contenedor tendrá su propia

jerarquía de procesos y su proceso padre o systemd (PID 1).

Figura 2-9. PID namespace

Page 50: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

28

o UTS namespace. Aísla los identificadores de sistema relacionados con el nombre de la máquina y

el dominio de la misma.

o MOUNT namespace. Aísla los puntos de montaje de los sistemas de ficheros que puede ver un

grupo de procesos, similar al funcionamiento original de chroot [9].

Figura 2-10. MOUNT namespace

o USER namespace. Aísla identificadores de usuarios y grupos. Así dentro un contenedor es posible

tener un usuario con ID 0 (root) que se corresponda con un ID de usuario sin privilegios en el

host.

o IPC namespace. Aísla los recursos de intercomunicación entre procesos dentro del espacio de

nombres.

o Cgroup namespace (a partir del kernel 4.6). Aísla la vista de los cgroups entre procesos dentro del

espacio de nombres.

Ambas tecnologías se han ido asentando paulatinamente hasta una completa integración en el kernel. Del mismo

modo, otros componentes del kernel han ido complementando el soporte al funcionamiento de los contenedores,

especialmente en términos de seguridad:

• Las Capabilities dota a los sistemas de virtualización de contenedores de una capa de seguridad

adicional ya que permite controlar y restringir las operaciones privilegiadas que pueden lanzar los

procesos que se ejecutan dentro de los contenedores, tales como el montaje de sistemas de ficheros,

cambio de fecha o la manipulación de interfaces de red, entre otras, aun siendo root. Las capabilities

necesarias pueden concederse o denegarse al arrancar el contenedor según se necesite.

• La integración de los contenedores con SELinux o AppArmor hace posible asociarles directamente

políticas de seguridad de control de acceso obligatorio, conocido también como MAC, que autorizan o

deniegan las operaciones que pueden hacer. Funciona de una manera similar a Capabilities, pero aporta

nuevas políticas de seguridad y además refuerza el control del host anfitrión frente a determinadas

acciones privilegiadas ejecutadas desde los contenedores.

2.3.4 Orquestación

Volviendo al paralelismo inicial de contendores y la arquitectura de microservicios, ya se ha demostrado como

los contenedores permiten desacoplar la capa de aplicación de la infraestructura subyacente, sin que ello penalice

en rendimiento y facilitando la construcción de los servicios. Además, la ligereza que los caracterizan

posibilitaría una fácil escalabilidad que los convierten en el perfecto candidato para el despliegue de

microservicios, por ejemplo, que estén basados en diferentes frameworks o lenguajes de programación.

Sin embargo, el enfoque de microservicios introduce otros requisitos, como los relacionados con la gestión de

los recursos, a nivel de despliegue y monitorización, cuando es necesario repartir las múltiples instancias que

conforman una aplicación o servicio entre diferentes máquinas y contenedores, garantizar la interconexión entre

ellos, o mantenerlos en un entorno dinámico y distribuido.

Frente a estos retos es esencial disponer de mecanismos de orquestación que abstraigan la complejidad de la

plataforma subyacente y automaticen la gestión de los despliegues de la propia infraestructura y los servicios

que alojan. En el contexto de los servicios multi-contenedor distribuidos, la orquestación se refiere al proceso

Page 51: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

29

29

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

de automatizar y gestionar un pool de máquinas, conocido comúnmente como clúster, en las que se ejecutan

contenedores, y configurar su comportamiento e interacción conjunta [10]. Engloba, en su concepto más amplio,

los siguientes procesos:

• Planificación ("scheduling"): decide la máquina donde correr la imagen de un contendor, para

equilibrar la carga o establecer las restricciones impuestas por el usuario en la configuración del

servicio.

• Afinidad ("affinity"): especifica que los contenedores se ejecuten en el clúster próximos o separados,

según se quiera satisfacer requisitos de rendimiento o disponibilidad.

• Monitorización ("health monitoring"): vigila el estado de los contenedores del clúster.

• Conmutación por error ("failover"): replanifica el despliegue de un contenedor para proporcionar

tolerancia a fallos.

• Escalado ("scaling"): agrega o retira máquinas del clúster en función de la demanda de carga.

• Enrutamiento de red ("networking"): proporciona una red superpuesta para la interconexión entre

contenedores del clúster.

• Descubrimiento de servicio ("service discovery"): permite localizar los contenedores en el clúster,

incluso cuando cambian de IP o se mueven entre máquinas.

• Actualizaciones contínuas ("rolling updates"): administra las actualizaciones de los contenedores para

evitar interrupciones de servicio o revertirlas en caso de fallo.

La gestión de clústeres de máquinas y la planificación ("scheduling") de contenedores son los dos componentes

clave en la implementación de servicios multi-contenedor sobre varias máquinas. Están estrechamente

relacionados, por lo que es normal que las soluciones de orquestación actuales integren ambas funciones. No

obstante, algunas soluciones de orquestación van más allá e incluyen balanceadores de carga, sistemas de

resolución de nombres de contenedores y mucho más. Algunos son extensibles y se integran con otros

frameworks que los complementan para agregar capacidades adicionales.

A continuación, se resumen a alto nivel algunas de las tecnologías de clustering y orquestación de código abierto

más extendidas:

2.3.4.1 Docker en modo Swarm

Desde su versión 1.12, el motor de Docker ("Docker Engine") integra Swarm como su solución nativa para la

orquestación y gestión de clúster de máquinas, denominados enjambres ("swarms"), provistas de Docker Engine

para ejecutar contenedores. Al estar completamente embebido en el Docker Engine, no es necesario la

instalación de ningún software de orquestación adicional, pudiendo crear el enjambre, desplegar los servicios de

aplicación al enjambre y administrar su comportamiento de la misma forma que se hacía con Docker Engine y

Docker Compose.

Swarmkit es el proyecto independiente que implementa la capa de orquestación de Docker.

Docker se activa en modo Swarm para crear un clúster nuevo o añadir a una máquina nueva al enjambre. En

este modo, cada una de las máquinas del clúster pasan a denominarse “nodos”. El escenario más habitual para

la creación de un swarm incluye nodos distribuidos entre múltiples máquinas físicas y servidores Cloud.

Otras características relevantes son:

• Servicio de tolerancia a fallos y replicación, que planifica ("scheduling") los contenedores en el clúster

en caso de problema en algún nodo.

• Redes superpuestas ("overlay") para la comunicación privada de los contenedores, con servicio DNS

embebido para el descubrimiento de servicios

• Alta disponibilidad mediante el uso de varios maestros

• Balanceo de carga interno

Page 52: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

30

• Monitorización del estado de salud de los servicios, recreando contendores si alguno deja de funcionar.

• Seguridad de red, forzando la autenticación y cifrado TLS de las comunicaciones entre nodos, usando

una Autoridad de Certificación.

A la hora de implementar un Docker en modo Swarm, los usuarios suelen recurrir a otra herramienta del

ecosistema Docker, Docker Machine.

2.3.4.2 Kubernetes

Kubernetes (K8s) es una solución de código abierto diseñado para para la automatización de despliegues, el

escalado y la gestión de aplicaciones en contenedores. Con Kubernetes, es posible decidir cuándo deben

ejecutarse los contenedores, aumentar o disminuir el tamaño de los contenedores de la aplicación o verificar el

consumo de recursos de las implementaciones de la aplicación. El proyecto de Kubernetes se basa en la

experiencia de Google en el trabajo con contenedores a escala masiva, y a día de hoy se encuentra bajo el

patrocinio de la Cloud Native Computing Foundation (CNCF).

Se implementa inicialmente para el propio uso interno de Google como orquestador de su sistema de recursos

en los datacenters.

Las características clave incluyen escalado automático incorporado, balanceo de carga, orquestación de

volúmenes y administración de secretos. Además, hay una interfaz de usuario web para ayudar a administrar y

solucionar problemas del clúster. Con estas características incluidas, Kubernetes a menudo requiere menos

software de terceros que Swarm o Mesos.

Las opciones para utilizar Kubernetes apenas tienen restricción, casi cualquier opción de uso es posible.

Kubernetes está tomando ventaja frente a otros orquestadores, al contar con un catálogo más amplio de

funcionalidades, si bien lo hace más complejo. Tiene una curva de aprendizaje más pronunciada y su

configuración puede requerir más esfuerzo que Swarm.

No obstante, gracias a todas las posibilidades de instalación que ofrece y porque muchas soluciones lo están

integrando en sus arquitecturas (se encuentra en todos los PaaS y en todos los servicios Cloud) se está

consolidando como la principal solución de orquestación. También prueba de ello fue el anuncio en octubre de

2017 de la integración de Kubernetes de forma nativa en Docker.

2.3.4.3 Apache Mesos + Marathon

La combinación de Apache Mesos con Marathon Mesosphere conforman una solución completa para la

orquestación de contendores.

Apache Mesos es un administrador de clústeres de código abierto que simplifica la ejecución de aplicaciones en

un clúster escalable de servidores. Mesos se describe como un kernel de sistemas distribuidos o, dicho de otra

forma, una plataforma de clúster que proporciona recursos computacionales a aplicaciones. Fue diseñado para

plataformas muy grandes y para ser extremadamente confiable. Es posible escalar Mesos a miles de nodos.

Mesos es el corazón del sistema Mesosphere, una solución de software que amplía las capacidades de

administración de clúster de Apache Mesos con componentes adicionales para proporcionar una forma nueva y

novedosa de administrar las infraestructuras de servidor. Al combinar varios componentes con Mesosphere,

como Marathon, permite escalar fácilmente las aplicaciones abstrayendo muchas de las complejidades asociadas

con este proceso. Adicionalmente, Mesosphere destaca por funciones tales como la planificación eficiente de

servicios (según consumo de CPU y RAM), escalado, tolerancia a fallas, alta disponibilidad (a través de

Zookeeper) y descubrimiento de servicios.

Apache Mesos es anterior a Docker, pero que agregó soporte para Docker integrando el framework Marathon.

Es, sin embargo, esta diversidad de componentes y posibilidades la que complica su configuración y

mantenimiento, en comparación con otras soluciones de orquestación.

Page 53: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

31

31

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

2.3.4.4 Comparativa

La siguiente tabla compara las diferentes soluciones de orquestación tratadas conforme a unos puntos

básicos que apoyen la decisión de la tecnología seleccionada para los casos de uso y requerimientos del

proyecto.

Docker Swarm Kubernetes Mesos+Marathon

Instalación del

clúster Fácil de instalar y configurar

Ligeramente complejo de

configurar

Complejidad variable,

dependiendo del escenario de

configuración

Despliegue de

contenedores Completamente nativo de

Docker

Basado en fichero YAML

para definir los servicios

del clúster

Basado en ficheros de

definición JSON

Tamaño

mínimo del

clúster

Un único nodo.

En entornos de producción, al

menos dos nodos gestores

para garantizar la alta

disponibilidad. También se

necesitan múltiples nodos

trabajadores para la

distribución y replicación de

servicios.

Un servidor maestro y un

servidor minion.

En entornos de

producción serán

necesarios al menos tres

nodos maestros, y tantos

minions como se

requiera.

Un maestro y un esclavo.

En entornos de producción

serán necesarios al menos tres

maestros, y tantos minions

como se requiera.

Escalabilidad

Adecuado para requisitos de

pequeña o media escala.

Despliegue rápido de

contenedores.

Adecuado para medios o

grandes clústeres.

Mayores garantías sobre

el estado del clúster, en

perjuicio de la agilidad de

escalado.

Adecuado para casos de escala

masiva.

Buena opción si se precisa

combinar contenedores y

aplicaciones normales en el

mismo clúster.

Principal

característica

Facilidad de uso y

aprendizaje. Margen de

usabilidad significativo.

Las mejores funciones de

planificación de pods [11]

cuando se requieren

implementaciones de

aplicaciones complejas.

Escala en miles, y

características de restricciones

basadas en rack /

máquinas disponibles para

ajustar con precisión dónde

desplegar las aplicaciones.

Tabla 2–4. Tecnologías de virtualización basadas en contenedores

En este proyecto se hará uso de Docker en modo Swarm, ya que es preferible en entornos donde se favorece la

simplicidad y el desarrollo rápido. Es la forma más compatible y natural de organizar las infraestructuras de

contenedores de Docker al estar nativamente integrado en el motor de Docker. En este sentido, es más flexible

y permitirá transicionar la aplicación en contenedores más fácilmente. Por otro lado, la aplicación del proyecto

no es compleja ni tiene requisitos de escala masiva.

Viendo el creciente interés y uso de contenedores de la comunidad tecnológica, los grandes fabricantes y

proveedores de servicios Cloud están cada vez más volcados en ofrecer soluciones de orquestación populares

en sus entornos, dando origen al modelo de computación Cloud CaaS, acrónimo de Contenedor como Servicio

("Container as a Service"). Este tema se tratará con mayor detalle en un apartado posterior.

Page 54: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

32

2.4 Cloud Computing

La transformación digital que sigue experimentando la sociedad está originando un incremento recurrente de las

necesidades de procesamiento, almacenamiento y conectividad de los sistemas de información para la provisión

de servicios que den cobertura a las demandas sociales y empresariales actuales. Estos requisitos unidos a ciertas

circunstancias tecnológicas como la reducción de coste de los componentes informáticos, o la mayor

conectividad vinculada al abaratamiento del acceso a la red e incremento de las velocidades de transferencia

alcanzados, han convergido en la concepción tecnológica del "cloud computing" o computación en la nube. El

cloud computing se refiere a la forma de proveer como servicio bajo demanda recursos informáticos, tales como

servidores, sistemas de almacenamiento, puestos de trabajo, servicios de correo, aplicaciones, bases de datos,

redes, entrega de contenido, etc., a través de Internet.

La evolución tecnológica en el campo de la virtualización ha sido un elemento clave en el desarrollo del modelo

cloud. La flexibilidad, elasticidad y escalabilidad que aporta la virtualización habilita a los proveedores cloud a

provisionar de forma ágil, con un alto grado de automatización, optimización de recursos y administración

simplificada, los recursos precisos requeridos por los clientes. Cuando se habla de elasticidad y escalabilidad se

refiere tanto al aumento de los recursos como a la disminución de los mismos, para evitar un sobre-

aprovisionamiento cuando la carga de trabajo se reduce o penalizar en rendimiento.

El concepto de cloud computing responde también a un modelo de negocio impulsado por grandes proveedores

cloud, como Amazon, Microsoft o Google, que cuentan con numerosos clientes y han alcanzado enormes

economías de escala con las que pueden ofrecer una gran variedad de servicios tecnológicos a precios

competitivos, contratados en la modalidad de pago por uso, y ajustados a las necesidades concretas de sus

clientes. Frente al modelo tradicional de datacenter interno, abstrae del coste de mantenimiento hardware de sus

sistemas o de inversiones adicionales por haber dimensionado incorrectamente la capacidad requerida por los

sistemas de información. Con los servicios cloud se paga por lo que se usa, con la posibilidad de aumentar o

reducir los recursos en cuestión de minutos según sea necesario, eliminando la necesidad de planificar en cada

momento la capacidad de la infraestructura y reduciendo los tiempos de aprovisionamiento. De esta forma, los

gastos iniciales y recurrentes son mucho más bajos, permitiendo centrar el esfuerzo en proyectos propios del

negocio.

Por otro lado, la globalidad alcanzada por los proveedores cloud asegura la disponibilidad de los servicios

redundados en múltiples regiones del mundo, con la consiguiente reducción de la latencia en el consumo de los

servicios para los clientes.

Conforme a la definición del cloud computing formulada por el NIST (National Institute of Standards and

Technology) en su publicación especial SP 800-145, un servicio cloud debe cumplir cinco características

esenciales [12]:

• Autoservicio bajo demanda: Un consumidor debe poder autoabastecerse de recursos informáticos como

la capacidad de almacenamiento o computación, en función de sus necesidades, sin que sea necesaria

interacción humana del proveedor del servicio.

• Accesibilidad desde la red: Los servicios ofrecidos deben ser accesibles independiente de localización,

a través de mecanismos estándares y desde diferentes plataformas con conexión a la red (ordenadores,

smartphones, tablets, etc.).

• Recursos compartidos: Los recursos deben estar puestos a disposición de todos los clientes, y son

asignados o reutilizados atendiendo a la demanda de dichos clientes. De esta forma, se consiguen

economías de escala que repercutirán en menores costes para los clientes.

• Elasticidad: Un cliente debe poder dimensionar a demanda los recursos de manera rápida, elástica, e

incluso automática, en prácticamente cualquier momento. Esto se traduce en un incremento sustancial

de la agilidad de los clientes para adaptarse los requisitos de su entorno. Los recursos ofrecidos deben

ser percibidos como ilimitados para el cliente.

• Servicio supervisado: Los sistemas cloud deben controlar y optimizar el uso de los recursos

automáticamente dotándose de mecanismos de medición que reporten de forma transparente tanto para

el proveedor de servicios cloud como para el cliente.

Page 55: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

33

33

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

2.4.1 Modelos de servicio

Los servicios ofertados por los proveedores cloud se pueden agrupar en tres tipologías fundamentales:

Infraestructura como Servicio (IaaS):

El modelo de servicio IaaS ofrece acceso bajo demanda a la infraestructura de TI (servidores, máquinas virtuales,

almacenamiento, redes, sistemas operativos) que se aprovisiona y administra a través de Internet, liberando a los

clientes de las actividades derivadas de la gestión de la capa física. Proporciona el más alto nivel de versatilidad

y control sobre los recursos de TI, similar la gestión de recursos de TI que se puede hacer en un entorno on-

premise, ya que el mantenimiento de todo el software está delegado en el cliente.

Plataforma como Servicio (PaaS):

En los servicios de tipo PaaS se provee de un entorno de desarrollo, con herramientas de programación,

middleware, sistemas de administración de bases de datos, servidores Web, etc., diseñado para liberar la

necesidad de administrar la capa de infraestructura, y centrarse en la implementación, despliegue y

administración de las aplicaciones. Así, abstrae de la preocupación de adquirir recursos y licencias, planificar la

capacidad necesaria o mantener el software en óptimas condiciones.

Software como Servicio (SaaS):

Los servicios SaaS proporcionan aplicaciones basadas en la nube completas que los clientes pueden usar a través

de Internet a demanda, pagando solo por el uso que se hace a través de una suscripción o del nivel de uso.

El proveedor de servicios cloud administra la infraestructura y toda la capa de software que soporta la aplicación.

También se encarga del mantenimiento, como la gestión de las actualizaciones software y revisiones de

seguridad. La infraestructura subyacente y tecnologías que dan soporte a la aplicación son transparentes a los

clientes.

Figura 2-11. Responsabilidad entre cliente y proveedor según modalidad de servicio

2.4.2 Cloud computing y contenedores - CaaS

Contenedores como Servicio (CaaS) es el nombre que ha recibido un nuevo modelo de servicio que entrega a

los usuarios un entorno provisto de todos los recursos necesarios para la gestión completa del ciclo de vida de

las aplicaciones, desde su desarrollo hasta su puesta en producción, mediante soluciones de virtualización basada

Page 56: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Estado de la técnica

34

en contenedores, herramientas de orquestación e infraestructura distribuida.

Al basarse en la tecnología de virtualización a nivel de sistema operativo, CaaS se situaría como capa intermedia

entre la infraestructura como servicio y la plataforma como servicio. De esta forma, se ofrece un servicio que

hereda los beneficios de los contenedores en cuanto a rendimiento, ocupación, escalabilidad y portabilidad, y

sin estar limitado a las herramientas o entornos de ejecución que proporcionan los proveedores en el modelo

PaaS.

Aunque es sólo un componente más, en el corazón de una plataforma CaaS se encuentran los orquestadores de

contenedores que, como ya se ha comentado en un apartado anterior, están diseñados para gestionar operaciones

tales como el despliegue de contenedores y la administración de clústeres de máquinas, entre otras cosas. Sin

embargo, los orquestadores por sí solos no resuelven la gestión del ciclo de vida completo de las aplicaciones.

Es por ello que los servicios CaaS integran otros componentes con los que completar el marco de trabajo, como:

• Paneles de administración para la gestión completa de todos los componentes y diversas API de

gestión.

• Servicio de registro para el almacenamiento y gestión segura de imágenes.

• Almacenamiento persistente de los datos.

• Balanceadores de carga que administren y distribuyan el tráfico externo.

• Controles de acceso basado en roles a todos los elementos, incluidos repositorios, nodos, secretos, redes,

volúmenes, etc. para los diferentes equipos de desarrollo participantes.

• Complementos de seguridad que permitan establecer comunicaciones seguras, autoridades de

certificación, gestión de secretos, escaneos de vulnerabilidades, firma de imágenes, etc.

• Monitorización, gestión de logs, recolección de métricas, análisis y programación de alertas.

• Mecanismos de integración continua, que agrega los cambios de código en un repositorio compartido

y son validados automáticamente, y de entrega continua, que prepara los cambios que hayan superado

pruebas automáticas para entregarlos en producción si es aprobado.

• Entornos de trabajo colaborativos donde compartir comentarios, reporting de errores, etc.

• Integración con otros servicios de proveedores cloud.

Estas características son generales y pueden variar en función del proveedor de servicios seleccionado.   

Si bien trabajar con CaaS añaden una capa de abstracción que simplifica la gestión de los contenedores, durante

todo su ciclo de vida, la decisión de usar Docker en modo Swarm directamente, sin el apoyo de alguna de las

soluciones tipo CaaS mencionadas. Esta decisión responde a la motivación de trabajar como mayor versatilidad

en la gestión de los contenedores y servicios desplegados en el swarm. De cara a la ejecución del proyecto es

necesario trabajar en un nivel más bajo para entender con mayor profundidad de detalle el funcionamiento y

opciones/alternativas que ofrece la tecnología. 

Page 57: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

35

3 HERRAMIENTAS

3.1 XPath

A lo largo del proyecto se han establecido condiciones específicas que obligan a recorrer y tratar documentos

XML, utilizados principalmente como ficheros de propiedades, con objeto de recuperar la información

contenida.

XPath (XML Path Language) [13] es un lenguaje de consulta que permite navegar a través de los elementos y

atributos de un documento XML para recuperar información. Es un estándar recomendado por W3C que fue

creado originalmente para su uso con el estándar de W3C XSLT (eXtensible Stylesheet Language for

Transformations) y contituye la base de otras especificaciones relacionadas.

El funcionamiento de XPath se basa en el modelado conceptual del documento XML como un árbol de nodos,

llamado modelo de datos.

El bloque de construcción básico de XPath es la expresión, siendo la más habitual la expresión de ruta, que se

utiliza para seleccionar un nodo o conjunto de ellos en un documento XML. En una expresión de ruta, los tramos

de la expresión ("steps"), es decir, cada parte separada por "/" o "//", son evaluados secuencialmente.

La sintaxis de las expresiones es similar a la estructura de un sistema de ficheros tradicional. Sin embargo, al ser

una especificación de coincidencia de patrones, su semántica es totalmente diferente. En un ejemplo sencillo, la

expresión /level1/level2 selecciona todos los elementos level2 que se encuentran debajo de un elemento level1.

Para seleccionar un elemento level2 específico, habría que indexar usando corchetes. Así, la ruta

/level1[3]/level2[2] seleccionaría el segundo elemento level2 debajo del tercer elemento level1.

XPath está soportado en Java SE (javax.xml.xpath).

3.2 PostgreSQL

PostgreSQL es un sistema avanzado de gestión de bases de datos relacionales (ORDBMS, Object-Relational

Database Management System) de código abierto. Respaldado por más de 15 años de desarrollo activo, tiene

una arquitectura comprobada, de clase empresarial avanzada, con la que ha logrado una sólida reputación debido

a sus características innovadoras, integridad, seguridad y fiabilidad.

Al igual que muchos otros proyectos de código abierto, el mantenimiento y mejora de PostgreSQL no está

controlado por ninguna compañía. Es un proyecto de comunidad y está respaldado por desarrolladores

voluntarios y entidades comerciales que contribuyen en su desarrollo. Dicha comunidad es conocida como

PGDG (PostgreSQL Global Development Group).

Uno de los claros beneficios de PostgreSQL es que se trata de un proyecto de código abierto, distribuido bajo

una licencia libre, la licencia PostgreSQL, que otorga la libertad a cualquier persona de usar, modificar, distribuir

PostgreSQL de manera gratuita, independientemente del propósito que se le vaya a dar, sea privado, comercial

o académico. Todo esto se traduce, además del indudable ahorro de licencias y reducción de costes, en un

impulso a la innovación conseguido con el trabajo colaborativo de la comunidad, en una mayor confiabilidad

del software por estar sometido a la inspección de un elevado número de personas, y un mayor control sobre el

código que permite adaptarlo a las necesidades particulares de cada uno.

3.2.1 Arquitectura básica

La estructura física de PostgreSQL es sencilla: incluye una memoria compartida reservada para cacheo de la

base de datos y del registro de transacciones, algunos procesos que operan en segundo plano y ficheros de datos.

A alto nivel, PostgreSQL está basado en una arquitectura cliente/servidor que sigue el modelo de "proceso por

usuario". En este modelo, un proceso servidor (backend) puede atender exclusivamente a un solo cliente. De

esta manera se permiten las conexiones concurrentes de diferentes clientes. En su funcionamiento, un proceso

Page 58: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

36

maestro postgres se queda escuchando esperando conexiones entrantes y se encarga de generar un nuevo proceso

para cada conexión. Desde ese momento, el cliente y el nuevo proceso del servidor se comunican sin la

intervención del proceso original de postgres.

Algunas de las características generales y funciones diferenciadoras de PostgreSQL, según su documentación

oficial, son:

• ACID compliant: asegura que las transacciones se ejecutan completamente o se anulan ("atomicity"),

no van a romper las reglas de integridad de la base datos cuando se acoplen los datos ("consistency"),

son independientes unas de otras ("isolation"), y persistirán una vez finalicen ("durability").

• Multiplataforma: se ejecuta en todos los principales sistemas operativos, incluidos Linux, UNIX (AIX,

BSD, HP-UX, macOS, Solaris) y Windows.

• Cumplimiento de estándares: compatible con la mayoría de los tipos de datos del estándar SQL:2016.

Admite caracteres de internacionalización, codificación multibyte, unicode, y es compatible con la

configuración regional para la clasificación, la distinción entre mayúsculas y minúsculas y el formateo.

• Escalabilidad: posee una gran escalabilidad tanto en la cantidad de datos que puede administrar como

en el número de usuarios concurrentes que puede manejar.

• Altamente configurable y extensible: dispone de interfaces nativas para la mayoría de los leguajes de

programación como C/C++, Java, .Net, Perl, Go, Python, Ruby, Tcl, ODBC, entre otros.

• Soporte: cuenta con el apoyo y contribución de una amplia comunidad dedicada de desarrolladores

profesionales, junto con una oferta de soporte comercial, disponible a empresas y usuarios.

• Funcionalidades avanzadas: controles de acceso granular, tablespaces, replicación asíncrona,

transacciones anidadas (savepoints), copias de respaldo en línea o en caliente, optimización de

consultas, herencia de tabla (es un concepto de bases de datos orientadas a objetos), etc.

PostgreSQL gestiona el acceso concurrente de manera eficiente mediante la implementación del control de

concurrencia multi-versión (MVCC - Multi-Version Concurrency Control). En contraposición del bloqueo a

nivel de tabla, se trata de un sistema que previene a los lectores de bloquear a los escritores y a los escritores de

bloquear a los lectores.

Para proveer de atomicidad y durabilidad, PostgreSQL utiliza la característica denominada registro de escritura

anticipada o WAL (Write Ahead Logging), que de forma resumida consiste en una técnica para retener a nivel

de disco (archivado de los ficheros WAL o REDO log) la descripción de los cambios hechos a la base de datos,

antes de sean escritos en la base de datos. El uso de WAL da como resultado un número significativamente

menor de escrituras en disco.

3.2.2 Por qué PostgreSQL

El presente proyecto se realiza bajo la premisa de no incurrir en costes directos, lo que limita el desarrollo a la

selección y empleo de herramientas de código abierto. En el ámbito de bases de datos relacionales, las principales

alternativas son MySQL y PostgreSQL, aunque la colección de características y prestaciones ofrecidas con

PostgreSQL es comparable a las de otras soluciones comerciales de bases de datos como Oracle o SQL Server.

La única similitud entre MySQL y PostgreSQL es que estos dos proyectos son de código abierto; aparte de eso,

ambos proyectos se fundamentan en concepciones tecnológicas muy diferentes. PostgreSQL ha centrado sus

esfuerzos en garantizar altos índices de fiabilidad, integridad de datos, y escalabilidad, aunque ello penalice en

el consumo de recursos y el rendimiento frente a otros sistemas de bases datos. Por otro lado, MySQL se ha

enfocado en la facilidad de uso y la optimización las operaciones, ofreciendo un mejor rendimiento y rapidez de

respuesta.

Page 59: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

37

37

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

3.3 MyBatis

MyBatis es un framework de persistencia de código abierto [14], que simplifica la persistencia de objetos en

bases de datos relacionales, separando la capa de negocio y la capa de base de datos. Soporta SQL,

procedimientos almacenados y mapeos avanzados.

Almacenar y recuperar datos hacia y desde bases de datos relacionales es un requisito muy común, y una parte

indispensable de muchas aplicaciones. La capa de persistencia implica la población de objetos Java con datos

cargados desde la base de datos mediante consultas SQL y la persistencia de los datos en objetos Java en la base

de datos mediante SQL. Aunque Java proporciona una API JDBC (Java DataBase Connectivity) para el acceso

a la base de datos, es una API de bajo nivel, y requiere una gran cantidad de codificación repetitiva para realizar

operaciones de base de datos, como la creación de una conexión, establecer los parámetros de entrada, liberar

los recursos, etc. Utilizando JDBC, la obtención de datos de una base de datos, la incorporación en objetos Java

y la persistencia de datos de objetos Java en una base de datos se convierte en un procesos poco eficiente y

tedioso. MyBatis abstrae y automatiza todas esas tareas comunes para que el programador pueda enfocarse en

los aspectos verdaderamente de valor a la aplicación, como preparar las sentencias SQL a ejecutar y pasar los

datos de entrada como objetos Java. Es decir, MyBatis adopta un enfoque simple que aprovecha los beneficios

de SQL, pero evita la complejidad de JDBC, reduciendo considerablemente el código de la aplicación y

facilitando la implementación de la persistencia de objetos.

MyBatis no es estrictamente un ORM (Object Relational Mapper), con el que se mapean objetos Java a tablas

de base de datos de la forma más directa y transparente posible. Con MyBatis se mapean las clases a sentencias

SQL o procedimientos almacenados que programa el desarrollador. En resumidas cuentas, las herramientas

ORM completas generan SQL, mientras que MyBatis usa SQL directamente. Al estar centrado en SQL, MyBatis

permite utilizar todas las funcionalidades de la base de datos como procedimientos almacenados, vistas,

consultas de cualquier complejidad o funcionalidades específicas del proveedor, permitiendo al programador

manipular el SQL para optimizar las sentencias para la consecución de los datos perseguidos.

La simplicidad es su mayor ventaja sobre las herramientas de mapeo relacional de objetos: asocia objetos, como

un JavaBean o un Map, con procedimientos almacenados o sentencias de SQL utilizando unos ficheros XML

descriptores, desde código Java mediante anotaciones o combinando ambas opciones. Para el proyecto se ha

preferido mantener externalizadas las sentencias SQL en ficheros XML, a fin de mantener claridad del código e

independencia entre las capas de datos y la lógica de negocio. Esta separación entre SQL y el lenguaje de

programación de la aplicación es un requisito del proyecto para poder aprovechar las capacidades de

automatización alcanzados en el proceso de generación de las clases del modelo de datos y posterior despliegue

del proyecto en el entorno de desarrollo.

Se utiliza habitualmente MyBatis para aplicaciones con bases de datos legadas, o poco normalizadas o cuando

es preciso tener el control total del SQL ejecutado, por ejemplo, porque el modelo de datos esté previamente

creado.

3.3.1 Utilización de MyBatis

De forma general y asumiendo que se cuenta con el modelo de datos de la base de datos y los objetos asociados,

los pasos para utilizar MyBatis son los siguientes:

• Configuración de los parámetros que definen el comportamiento global del framework en ejecución.

Cada proyecto de MyBatis tiene un fichero de configuración XML primario, altamente parametrizable,

en el que se definen a alto nivel los parámetros de conexión JDBC a la base de datos (dataSource), la

configuración en el manejo de las transacciones, la definición de alias para los tipos Java (typeAliases),

los manejadores externos o personalizados de tipos Java no soportados o no estándares (typeHandler)

para convertir los valores de los PreparedStatement o los ResultSets devueltos de las sentencias SQL, y

la localización de los ficheros XML de mapeo (mappers).

• Definición de los Mapped Statements o ficheros XML de mapeo.

Los ficheros XML denominados mappers contienen las sentencias SQL y las definiciones de mapeo

(SQL mapped statements). La potencia de MyBatis radica en la gestión de los Mapped Statements. En

estos ficheros se establece la configuración de cómo guardar y recuperar los objetos usando sentencias

Page 60: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

38

SQL y el tratamiento de los ResultSets devueltos. Según las sentencias que se deban lanzar, los mappers

contendrán elementos XML de tipo insert, delete, update o select en los que se definan las sentencias

SQL correspondientes.

MyBatis es capaz de automatizar el proceso de establecer los parámetros de consulta a partir de las

propiedades de los objetos de entrada de Java, y mapear las columnas devueltas en una consulta con las

propiedades del JavaBean relacionado en base a las coincidencias de sus nombres. Para el caso de

sentencias más complejas, se puede definir en el fichero XML un elemento ResultMap que describa la

relación entre columnas y propiedades de la clase Java en cuestión. El elemento ResultMap es el

elemento más importante y potente de MyBatis, cuyo uso equivaldría al 90% del código que JDBC

necesitaría para obtener datos de ResultSets.

A través de los ResultMaps, MyBatis también soporta el mapeo de resultados del tipo one-to-many o

many-to-many. Estas relaciones se pueden cargar de diferentes formas: mediante Selects anidadas que

se ejecutan desde el propio ResultMap para devolver los tipos complejos perseguidos, o mediante

ResultMaps anidados que tratan los datos repetidos de ResultSets resultante de consultas con joins entre

tablas. Se recomienda la opción de los ResultMaps anidados para evitar el "problema de las N+1 Selects"

que puede originar un impacto considerable de rendimiento cuando ser trabaja con volúmenes elevados

de datos.

• Creación del código Java para la invocación de los Mapped Statements y recuperación de los objetos

mapeados con la base de datos.

MyBatis simplifica significativamente el código, en comparación con JDBC. Por lo general, las líneas

de código necesarias para ejecutar una mapped statement se reducen en la mayoría de los casos a una.

3.3.2 Características adicionales

A continuación, se enumeran otras características o funcionalidades de interés del framework MyBatis que

colaboran en facilitar la implementación de la lógica de persistencia:

• Integración con otros frameworks de desarrollo: proporciona soporte de integración con los populares

frameworks de inyección de dependencias Spring y Guice, simplificando aún más el trabajo con

MyBatis.

• Lazy loading: puede cargar las consultas de forma diferida, hasta el momento en que se requieren sus

datos relacionados, evitando el coste de lanzar todas las consultas de las relaciones a la vez.

• Caché: Por defecto la única caché activa es la caché local de sesión que se utiliza para evitar dependencias

circulares y acelerar ejecuciones repetidas de consultas anidadas, únicamente durante la duración de una

sesión. MyBatis incorpora una funcionalidad de caché transaccional de segundo nivel muy potente, y

también se integra con varias bibliotecas de caché de terceros, como EHCache, Memcached, Ignite y

Hazelcast.

• SQL dinámico: en cualquier Mapped Statement, permite la creación de consultas SQL dinámicas basadas

en los parámetros de entrada. Utiliza expresiones con elementos del tipo if, foreach, choose (when -

otherwise), trim (where - set) o bind.

• Anotaciones: para implementar los Mapped Statements pueden usarse anotaciones en las clases mapper,

sin necesidad de utilizar ningún fichero XML. Sin embargo, cuando las sentencias son más complejas

presentan ciertas limitaciones y no alcanzan la misma flexibilidad y potencia que la configuración en los

ficheros XML.

3.3.3 Ventajas frente a herramientas ORM

Claramente MyBatis es una alternativa directa a la programación de acceso a bases de datos con una API JDBC.

No obstante, proporciona ciertas ventajas que, en determinados escenarios, lo convierte en una mejor opción

que las soluciones ORM. MyBatis combina lo mejor de trabajar a nivel SQL y del mapeo ORM. Consigue una

gran flexibilidad y ser reutilizable, pero evita la complejidad de JDBC, al mismo tiempo que otorga la facilidad

de mapeo de las herramientas ORM, sin tener su rigidez; sin embargo, no debe ser utilizado cuando se requiere

de una automatización total y transparente de la persistencia [15].

Page 61: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

39

39

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Las soluciones ORM completas, como Hibernate, son más avanzadas y proveen de una mayor transparencia

antes cambios del modelo de objetos, dado que generan las sentencias SQL de forma dinámica. Puede crear un

esquema de base de datos de acuerdo con un modelo de objetos Java. Lo anterior confirma que Hibernate

funciona mejor cuando la aplicación está enfocada en el objeto más que en la base de datos, aunque esto exige

tener un control total del esquema. Por ello, no es recomendable el uso de Hibernate en escenarios donde hay

una importante discrepancia entre el modelo de objetos y el modelo de datos.

A modo de resumen, en la siguiente tabla se recogen las principales propiedades de Hibernate y MyBatis que lo

diferencian.

MyBatis Hibernate

Requiere conocimientos de SQL. El

desarrollador es el encargado de programar las

sentencias.

Fomenta el trabajo con objetos de entidades y

genera las sentencias SQL necesarias, lo que implica

un ahorro de tiempo.

Se puede aprovechar las características

específicas de la base de datos y preparar

consultas SQL optimizadas. Mejor rendimiento.

Se pierde el control de las sentencias que realmente

se están ejecutando.

Más simple y flexible, con una curva de

aprendizaje más rápida. Fuerte curva de aprendizaje. Tiene múltiples

opciones para formar consultas: SQL, HQL, Criteria

API.

Centrado en SQL, dependiente de la base de

datos. Mantenimiento más costoso. Orientado a objetos. Lo hace relativamente

independiente de la base de datos.

Mapea ResultSets de la API JDBC a objetos Java.

No es relevante la estructura de tablas de la base

de datos. Mejor uso con base de datos pre-

existentes.

Mapea objetos Java a tablas de la base de datos.

Eficaz cuando se tiene el control completo sobre el

esquema de la base de datos.

Tabla 3–1. Comparativa MyBatis - Hibernate

3.4 API JAX-WS – proyecto Metro

En la especificación JSR 224 - JAX-WS 2.0 (Java API for XML Web Services) se establecen los fundamentos

para la creación de servicios Web basados en SOAP en Java. La implementación de referencia de JAX-WS

forma parte de las plataformas Java SE y Java EE. 

Al utilizar JAX-WS, el desarrollo de servicios web y clientes se simplifica con una mayor independencia de la

plataforma para aplicaciones Java mediante el uso de proxies dinámicos y anotaciones Java. Aunque los

mensajes SOAP son complejos, la API JAX-WS oculta esta complejidad del desarrollador de la aplicación. En

el lado del servidor, simplemente hay que especificar las operaciones del servicio Web definiendo métodos en

una interfaz escrita en el lenguaje de programación Java, y desarrollar una o más clases que implementan esos

métodos. En el lado cliente, se crea un proxy (un objeto local que representa el servicio) y luego simplemente se

invocan métodos en el proxy. El runtime de JAX-WS se encarga de leer o generar los mensajes SOAP,

permitiendo al desarrollador centrarse en la tarea de programar la funcionalidad que implementan los servicios,

y abstrayéndole de los mecanismos de invocación de éstos.

Existen varias implementaciones de la especificación como CXF o Axis2. El proyecto Metro, perteneciente a la

comunidad GlassFish, es el que desarrolla el código base para la implementación de referencia (JAX-WS RI)

de la especificación, como un componente dentro de su pila de servicios Web (Web service stack). Los

componentes que constituyen la distribución de Metro son: 

•  WSIT (Web Services Interopartibility Technologies): subsistema que incluye diferentes APIs de Java

que implementan varias especificaciones WS-* con las que se puede extender el protocolo SOAP y

ampliarlo con funcionalidades avanzadas empresariales. Así, proporciona funciones de servicios Web

como mensajería confiable, transacciones atómicas, o seguridad y confianza. 

Page 62: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

40

• JAX-WS RI (Java API for XML-Based Web Services Reference Implementation): framework de

desarrollo de servicios Web. Proporciona todas las herramientas y características básicas para la

interoperatividad de los servicios Web (mensajería SOAP, procesamiento WSDL, transmisión de datos

binarios con MTOM, WS-Addressing, etc.). JAX-WS forma parte de la plataforma Java SE desde la

edición 6 (Java SE 6).

• JAXB (Java Architecture for XML Binding Reference Implementation): implementación de referencia

de la especificación JSR-222, es una tecnología de Java que proporciona una capa de correlación

bidireccional entre las clases de Java y documentos XML; es decir, JAX-WS se apoya en JAXB para

mapear de un modo sencillo clases Java con los tipos de datos de un esquema XML, y así simplificar

el desarrollo de los servicios Web.

Figura 3-1. Proyecto Metro

Las operaciones que realiza JAXB de convertir una clase Java en un esquema XML y, al contrario, de

un esquema XML obtener su correspondiente clase Java, se conoce como serialización ("marshalling")

y deserialización ("unmarshalling") respectivamente. El paquete de enlaces de JAXB, javax.xml.bind,

define las interfaces y las clases abstractas que se utilizan directamente con las clases de contenido.

Además, el paquete contiene las API de serialización y deserialización.

Java proporciona cuatro herramientas de línea de comando para facilitar el desarrollo de servicios Web, dos de

la cuales se usan en el tratamiento de documentos WSDL y las otras en la conversión entre esquemas XML y

clases de Java:

• xjc: es un compilador de esquemas ("binding compiler") que genera clases JavaBeans con las

propiedades descritas en el esquema XML origen y las anotaciones JAXB necesarias por la API para

procesar los documentos XML. Es posible personalizar y extender XJC con el fin de alterar la

configuración predeterminada y controlar las correlaciones con las clases Java generadas.

• schemagen: genera esquemas XML (fichero con extensión .xsd) desde clases Java. Una vez creado el

esquema, JAXB puede convertir documentos XML asociados al esquema en y desde objetos Java, en

los procesos de marshalling y unmarshalling.

• wsgen: genera artefactos portátiles JAX-WS a partir de la implementación del endpoint del servicio

Web y la invocación del servicio web. Adicionalmente, puede generar un archivo WSDL y el

correspondiente documento de esquema XML.

• wsimport: genera artefactos portátiles JAX-WS a partir de un documento WSDL dado. Estas clases

facilitan el desarrollo de clientes, y también de servicios en un modelo de diseño descendente (contract-

first).

Además de usar las herramientas de línea de comandos también es posible invocarlas como una tarea Ant [16].

En la implementación del servicio web se ha usado la versión 2.3.1 de Metro que implementa la versión 2.2.11.

La versión de Java SE empleada ya incorpora una implementación de la última API de JAX-WS 2.2; sin

embargo, no contiene todas las dependencias de JAX-WS necesarias que pertenecen a la especificación Java

EE, como el servlet com.sun.xml.ws.transport.http.servlet.WSServlet o algunas clases del paquete

javax.transaction, para que el servicio Web pueda desplegarse en un contenedor servlet sobre Tomcat, que no

es un servidor Web completo de Java EE.

Page 63: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

41

41

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

3.4.1 Parte servidora JAX-WS

JAX-WS impone la existencia de un SEI identificada con la anotación @WebService (javax.jws.WebService).

Se conoce como Service Endpoint Interface (SEI) a la interfaz Java que expone las operaciones de una interfaz

de servicio web en términos de métodos abstractos de Java. Es decir, los clientes se comunican con servicios

web basados en SOAP a través de sus interfaces SEI. La clase Java que implementa los métodos definidos en el

SEI se le denomina Service Implementation Bean (SIB).

Es posible desarrollar un servicio usando JAX-WS mediante dos enfoques de partida: a partir de un documento

WSDL dado (enfoque descendente o contract-first) o desde una clase Java que implementa el servicio (enfoque

ascendente o code-first).

De forma general, el enfoque de desarrollo de un servicio Web recomendado es el descendente, partir de un

fichero WSDL para luego generar el código que implemente los servicios. De esta forma, se refuerza el concepto

de que un servicio es una entidad abstracta, neutral a su implementación. También exige una mayor dedicación

en planificar y diseñar la interfaz exacta requerida por el servicio antes de comenzar a codificar. El enfoque

ascendente se emplea habitualmente en los que se necesite habilitar una aplicación existente, apoyado en las

anotaciones del código que habría que añadir.

En cualquier caso, una implementación válida de un servicio web es una clase java que cumple los siguientes

requisitos [17]:

• La clase que implementa el endpoint debe estar anotada con javax.jws.WebService o

javax.jws.webServiceprovider (si se desea trabajar directamente a nivel de mensajes XML).

• La clase que implementa el endpoint podría referenciar de forma explícita un SEI con el atributo

endpointInterface de la anotación @WebService, sin ser obligatorio. Si no se especifica el atributo, se

define un SEI implícito para la clase anotada.

• Los métodos del SEI deben ser public y no declarados como static o final.

• Los métodos del SEI expuestos en el servicio Web deben estar anotados con javax.jws.WebMethod.

• Los métodos del SEI expuestos en el servicio Web deben tener tipos de parámetros de entrada y

devueltos compatibles con JAXB [18].

• SEI no puede ser declarada final ni ser una clase abstracta.

• SEI debe tener un constructor público por defecto.

• SEI no debe implementar el método finalize().

Tanto si se sigue un enfoque de desarrollo ascendente como descendente, las herramientas que provee Java se

pueden usar en el proceso de implementación del servicio Web. En el caso de wsimport, la herramienta da

soporte al enfoque en sentido descendente y genera todos los artefactos Java portables del servicio Web, tanto

para la parte del servidor como del cliente, para poder invocar a las operaciones del servicio web de forma

correcta. wsimport procesa el fichero WSDL y los esquemas XML, y genera artefactos tales como:

• Interfaz Java anotada correspondiente al Service Endpoint Interface (SEI), equivalente al elemento

portType del documento WSDL. Esta interfaz se utiliza para implementar el endpoint del servicio Web

o para crear instancias de cliente proxy dinámico.

• Clase que extiende la clase javax.xml.ws.Service. Representa al elemento service del documento

WSDL, y es utilizada para instanciar al SEI en un cliente proxy dinámico. Proporciona la vista del

cliente de un servicio Web.

• Clases de excepción mapeados desde los elementos fault del WSDL que hubiera.

• Clases correspondientes a los elementos input y output/response de cada operación del servicio Web.

• Beans de datos generados por JAXB a partir de los tipos de datos de los esquemas XML.

• Clase Objectfactory para facilitar la instanciación interna de las clases input y output/response.

Page 64: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

42

• Clase package-info, que anota el paquete java donde están ubicados las clases Java generadas a partir

de los esquemas XML del WSDL. Toma como referencia el targetNamespace para determinar la

estructura de carpetas.

Figura 3-2. wsimport: equivalencia namespace WSDL / estructura de carpetas

En la siguiente tabla se representa la correlación de los elementos del fichero WSDL con las clases Java que son

generadas al ejecutar wsimport:

WSDL Java

TargetNamespace Nombre del paquete

PortType Nombre del SEI

Operation Nombre del método

Part Parámetro de entrada y valor devuelto

Type Parámetro de entrada y valor devuelto

Fault Clase de Excepción

Binding Anotación javax.jws.soap.SOAPBinding

Service Atributo serviceName de la anotación javax.jws.WebService

Tabla 3–2. wsimport: equivalencia WSDL / Java

Según la especificación de servicios Web para Java EE (JSR-109), los servicios Web para Java pueden

implementarse de varias formas: como una clase Java que se ejecuta en un contenedor Web (modelo de

despliegue basado en servlet), o como un EJB (Enterprise JavaBean) de sesión stateless o singleton en un

contenedor EJB. Como se verá en el próximo capítulo, se ha optado por desplegar en un contenedor de servlet

Tomcat el archivo WAR que empaqueta los artefactos generados y el archivo WSDL junto con la

implementación del SEI correspondiente al servicio Web del PIDS desarrollado.

3.4.2 Parte cliente JAX-WS

De acuerdo con la especificación de servicios Web para Java EE, JAX-WS proporciona soporte para el modelo

de cliente de servicio Web dinámico (API Dispatch) y estático (API Dynamic Proxy). Ambos casos permiten la

invocación síncrona y asíncrona de servicios Web de JAX-WS.

El modelo de programación del cliente estático para JAX-WS es el llamado cliente de proxy dinámico. El cliente

de proxy dinámico invoca un servicio web dinámicamente, en tiempo de ejecución, basado en una interfaz del

endpoint de servicio (SEI) generado. Tras crear el proxy (interfaz/clase que extiende javax.xml.ws.Service), el

cliente puede utilizar los métodos del proxy y acceder a la implementación del servicio Web utilizando los

métodos especificados en el SEI. Los clientes de servicio web JAX-WS que utilizan el modelo de programación

de proxy dinámico pueden utilizar la herramienta wsimport, que procesa el archivo WSDL del servicio Web y

generar artefactos Java portátiles con los que crear el cliente del servicio Web. En general, el transporte,

codificación y dirección del endpoint son transparentes para el cliente. El cliente solamente necesita realizar

Page 65: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

43

43

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

llamadas sobre el SEI, siendo incapaz de distinguir si los métodos a los que llama están ejecutándose en local o

en remoto, ni tampoco puede saber cómo está implementado el servicio (servlet, EJB, etc.).

Sin embargo, si se prefiere trabajar directamente con XML, con la estructura del mensaje o con la estructura de

la carga de datos del mensaje, en lugar de con una abstracción de Java, la API Dispatch (javax.xml.ws.Dispatch)

permite desarrollar un cliente de servicio web dinámico conocido como cliente de asignación.

Para las demostraciones sobre el funcionamiento del servicio Web desarrollado en el proyecto se hará uso de un

cliente de proxy dinámico, basado en el modelo de programación de cliente estático.

3.5 AWS

Amazon Web Services (AWS) es el conjunto de servicios Web con lo que Amazon proporciona servicios de

infraestructura de TI, que constituye su plataforma de cloud computing pública. Amazon fue el pionero en

ofrecer el exceso de recursos de TI como modelo de negocio, y hoy en día es uno de los proveedores de servicios

más importantes en el panorama del cloud computing. Desde 2006 ha ido evolucionando, ofreciendo en la

actualidad un amplio catálogo de servicios de infraestructura, como capacidad de procesamiento, opciones de

almacenamiento, herramientas de desarrollo, redes y bases de datos que se ofrecen a demanda, con

disponibilidad inmediata y en una modalidad de pago por uso.

AWS ofrece sus servicios a cientos de miles de clientes activos en más de 190 países alrededor del mundo.

Dispone de centros de datos repartidos por el globo, estando su infraestructura global agrupada por regiones y

zonas de disponibilidad. Una región es un área geográfica del mundo independiente que tiene varias ubicaciones

aisladas llamadas zonas de disponibilidad. Cada zona de disponibilidad consta de uno o más centros de datos,

cada uno con energía redundante, redes y conectividad, alojados en instalaciones separadas. Las zonas de

disponibilidad de una misma región están conectadas mediante enlaces de baja latencia. Con esta segmentación

AWS puede proporcionar redundancia, tolerancia a fallos y alta disponibilidad con total flexibilidad para

recursos, como instancias o datos, en varias ubicaciones.

3.5.1 Productos y servicios

Amazon Web Services ofrece más de 90 productos basados en cloud agrupados en diferentes categorías, entre

las que destacan los servicios de computación, almacenamiento, bases de datos, redes y entrega de contenido,

productividad empresarial, análisis, herramientas para desarrolladores, herramientas de administración,

seguridad, IoT, y móviles.

AWS ofrece una suscripción gratuita durante 12 meses para tener una experiencia práctica con la plataforma, y

una amplia selección de productos y servicios de AWS. Las capacidades ofrecidas por la suscripción gratuita

son suficientes para montar la plataforma de simulación y testeo en el cloud sobre la que se evaluará el servicio

de información demográfica objeto del presente proyecto.

Page 66: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

44

Algunos de los productos empleados en el proyecto, cuya configuración y uso específico se desarrollará

en el capítulo sobre el trabajo realizado, son los siguientes:

Amazon EC2

Amazon Elastic Compute Cloud (Amazon EC2) es el servicio Web a través del cual se puede solicitar y

aprovisionar capacidad de computación escalable. Ofrece la posibilidad de crear entornos informáticos virtuales

en el cloud, aumentando o disminuyendo su capacidad a demanda, arrancando nuevas instancias (escalado

horizontal) o incrementado las prestaciones de las instancias desplegadas (escalado vertical) en cuestión de

minutos. Una instancia EC2 no es más que una máquina virtual en AWS sobre la que el usuario tiene el control

completo a través de las API del servicio Web. AWS proporciona varios tipos de instancias, que varían

principalmente en prestaciones de CPU y memoria, según las necesidades de rendimiento respectivas del

usuario. También permite elegir el sistema operativo de la instancia a partir de Imágenes de Máquina de Amazon

(AMI o Amazon Machine Image), entre cuyas opciones se incluyen varias distribuciones de Linux y Microsoft

Windows Server.

Amazon EC2 está diseñado para integrarse con la mayoría de los servicios de AWS, como Amazon Virtual

Private Cloud (Amazon VPC) o Amazon Elastic Block Store (Amazon EBS), el primero para proporcionar una

funcionalidad de red sólida a los recursos de TI, y el segundo como almacenamiento de soporte. De esta forma

AWS es capaz de proveer de una plataforma virtual completa ajustada a las necesidades de procesamiento y

almacenamiento particulares de cada cliente.

Un apartado en el que AWS hace especial hincapié es la capa de seguridad que envuelven todos sus servicios.

En este sentido, Amazon EC2 ofrece diferentes funcionalidades y características que la convierte en una solución

segura. Por ejemplo, los grupos de seguridad ("security groups") que se vinculan a las instancias EC2 funcionan

como un firewall virtual en el que se especifican reglas con los protocolos, puertos y rango de direcciones IP

que pueden alcanzarlas, así como el tráfico de salida permitido. Otros ejemplos serían la criptografía de clave

pública para el inicio de sesión y obtener el acceso de forma segura a la instancia, políticas de control de acceso

a los recursos de Amazon EC2, o la configuración de redes virtuales aisladas de forma lógica del resto del cloud.

Amazon VPC

Amazon Virtual Private Cloud (Amazon VPC) permite aprovisionar un entorno virtual, denominado nube virtual

privada (VPC), aislado lógicamente del resto de redes virtuales. Se pueden utilizar los recursos de AWS dentro

de la red de Amazon VPC y ahí crear instancias de Amazon EC2. El usuario tiene el control completo de la red,

pudiendo configurarla con los elementos propios de una red tradicional como el rango de IP, las subredes, las

tablas de enrutamiento o las puertas de enlace a Internet.

Al igual que con las instancias EC2, también se pueden establecer grupos de seguridad a nivel de VPC y

subredes, así como listas de control de acceso a la red.

AWS IAM

La herramienta de seguridad de AWS Identity and Access Management (IAM) complementa al resto de servicios

dotándolos de mecanismos avanzados de control de acceso de los usuarios y recursos de AWS. IAM controla

las medidas de identificación y autenticación, locales o federadas, claves de acceso, autenticación multifactor

(MFA), dispositivos permitidos, etc. Con IAM se pueden crear usuarios o grupos de usuarios, concederles

credenciales de seguridad, granularizar los privilegios de acceso mediante roles hasta el nivel de las operaciones

que pueden realizar sobre los recursos o servicios de AWS, e incluso restringir aún más los permisos en base a

condiciones específicas. Además, se pueden delegar permisos para crear y administrar recursos de AWS a otros

servicios de AWS utilizando roles definidas en IAM.

Amazon ELB

Amazon Elastic Load Balancer (ELB) es el servicio de balanceo de carga que distribuye el tráfico entrante entre

varios destinos, como instancias de EC2, contenedores y direcciones IP. Propicia la tolerancia a fallos y

Page 67: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

45

45

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

consistencia en rendimiento de las aplicaciones al equilibrar las cargas de tráfico, y aún más al poder repartirlas

entre varias zonas de disponibilidad.

ELB ofrece tres tipos de balanceadores, en función de si opera a nivel de aplicación (capa 7) para tráfico HTTP

y HTTPS (ALB o Application Load Balancer), a nivel de transporte (capa 4) para carga de tráfico TCP (NLB o

Network Load Balancer), o con aplicaciones que se construyeron dentro de la red EC2- Classic (CLB o Classic

Load Balancer). Todos ellos garantizan la escalabilidad, rendimiento y seguridad para obtener un alto nivel de

tolerancia a fallo para cualquier aplicación.

Amazon EBS

 Amazon ofrece varias opciones de almacenamiento de datos, con diferentes prestaciones de rendimiento y

durabilidad, que pueden combinarse para ajustarse a los requerimientos particulares de los usuarios y cargas de

trabajo.

Amazon Elastic Block Store (EBS) proporciona volúmenes de almacenamiento de nivel de bloque fácilmente

escalables y diseñados para utilizarlos con instancias EC2 en ejecución que se encuentren en la misma zona de

disponibilidad. Son persistentes al ciclo de vida de las instancias, aunque sólo pueden estar vinculadas a una sola

en cada momento. Ofrecen un rendimiento de I/O de disco constante y de baja latencia, lo que lo convierte en

una opción adecuada para bases de datos relacionales. Amazon EBS asegura la protección de los datos en reposo

y tránsito (datos que se mueven entre el volumen y la instancia) con características de cifrado y la configuración

de políticas de control de acceso en IAM.

3.6 Docker

Docker [19] se han impuesto prácticamente como el estándar de facto para la administración de contenedores.

Cuenta con el apoyo de las grandes compañías del sector tecnológico, asegurando su continuidad y evolución

continua, y proporciona una suite de herramientas que facilitan su empleo sin prácticamente tener que conocer

su funcionamiento interno. Por todo ello, será la solución empleada en el desarrollo del presente proyecto.

Tras una breve introducción, este apartado está dedicado a describir los conceptos y componentes de su

arquitectura interna, los modelos habituales de despliegue, así como algunos comandos básicos empleados en la

gestión de los contenedores, con el objeto de facilitar la comprensión y seguimiento del trabajo desarrollado.

3.6.1 Introducción

Docker empaqueta aplicaciones o servicios en contenedores, unidades estandarizadas que incluyen todo lo

necesario para su ejecución, incluidas bibliotecas, herramientas de sistema, código y entorno de ejecución. Su

eslogan “Build, Ship, and Run Any App, Anywhere” resume perfectamente las principales funciones de uso:

Docker dota de un sistema para implementar y ajustar la escala de aplicaciones rápidamente en cualquier

entorno, desde el desarrollo hasta la operación, con independencia del sistema operativo de las máquinas que

alojen los contenedores, consiguiendo así un proceso de integración ágil en las pruebas y despliegues.

Docker está disponible es dos ediciones: Community Edition (CE) y Enterprise Edition (EE).

Docker Community Edition (CE) es la plataforma pensada para desarrolladores y pequeños equipos

que están comenzando a experimentar con Docker y las aplicaciones basadas en contenedores

Docker Enterprise Edition (EE) está diseñado para el desarrollo empresarial y equipos de IT que

despliegan aplicaciones productivas en escala. Es una solución del tipo Container-as-a-Service (CaaS)

que proporciona a las empresas una solución para implementar cualquier aplicación distribuida en

cualquier infraestructura, tanto on-premise como Cloud [20].

3.6.2 Arquitectura, componente y comandos básicos

Es conveniente introducir brevemente el concepto de imagen, muy recurrente en la terminología de Docker, y

que más adelante se tratará con más profundidad. Las imágenes se podrían entender como un componente

estático, de sólo lectura, que contienen todo lo necesario para ejecutar un ejecutar un software, incluyendo el

Page 68: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

46

código, el entorno de ejecución, bibliotecas, variables de entorno y archivos de configuración. En este sentido,

un contenedor en Docker es la instanciación o ejecución de una imagen, pudiendo ejecutar varios contenedores

a partir de una misma imagen.

En Docker, su arquitectura está integrada por cuatro componentes: el motor de Docker (Docker Engine),

containerd, containerd-shm y runC.

Figura 3-3. Arquitectura Docker

Docker Engine es el principal punto de entrada de Docker. Es responsable de construir la imagen Docker,

orquestación, administración de volúmenes, redes, escalado, etc.

Docker Engine es una aplicación cliente-servidor: un cliente Docker lanza instrucciones a un proceso demonio

Docker (dockerd) que escucha las peticiones del cliente y se encarga de las tareas de construir, ejecutar, distribuir

y mantener los contenedores, imágenes, volúmenes y redes. Aunque incluye un cliente en línea de comandos

(CLI), el comando docker, Docker Engine permite la interactuación con cualquier cliente, local o remoto, que

consuma las interfaces de su API REST (Docker Engine API).

Una vez que Docker Engine reciba la solicitud para ejecutar una imagen, delega la responsabilidad al demomio

de containerd (docker-containerd), que administra el ciclo de vida completo del contenedor. containerd permitió

desprender la supervisión de los contenedores del Docker Engine y en un demonio separado.

El proceso runC es el responsable de la creación e inicio del contenedor, es decir, es el entorno de ejecución de

un contenedor. Se ocupa de la interfaz de bajo nivel (libcontainer) con las funcionalidades del kernel de Linux

como cgroups o namespaces, pero de acuerdo con las especificaciones de la Iniciativa Open Containers (OCI)

[21].

De forma general, la secuencia de ejecución interna de un contenedor en Docker se resume de la siguiente

forma:

• Docker Engine recibe la instrucción de ejecutar una imagen Docker.

• Docker Engine delega la responsabilidad de administrar el ciclo de vida completo del contenedor a

containerd.

• containerd descarga o transfiere la imagen desde el repositorio y almacena la imagen. Crea el sistema

de archivos raíz antes de llamar al contenedor-shim con la configuración del contenedor.

• containerd-shim usa runC para crear e inicializar el contenedor.

• Cuando el contenedor arranca, runC finaliza para permitir contenedores sin procesos demonios.

• El ciclo de vida restante del contenedor es administrado por containerd a través de container-shim (hay

un proceso containerd-shim por cada contenedor).

Este esquema da la capacidad de reiniciar o actualizar el motor sin impacto sobre los contenedores en

ejecución.

Page 69: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

47

47

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Muchos de estos componentes han sido donados por Docker a proyectos independientes en su empeño por

dotar mayor modularidad a su arquitectura, al mismo tiempo asegurar la neutralidad con otros actores de la

industria (proveedores de servicios Cloud y otros servicios de orquestación).

3.6.2.1 Imágenes Docker

Ejecutar una aplicación en Docker comienza con la construcción u obtención de una imagen Docker. Una

imagen Docker es un archivo tar que contiene todos los archivos, bibliotecas, binarios e instrucciones necesarias

para ejecutar una aplicación. Es básicamente el sistema de archivos que usarán los contenedores que se creen a

partir de ella.

Existen múltiples imágenes, públicas o privadas, de aplicaciones y servicios proporcionados por sus propios

fabricantes, preparadas para ser usadas en cualquier sistema de Docker. Así, es fácil encontrar imágenes con

aplicaciones preinstaladas como por ejemplo servidores web o motores de bases de datos, que se pueden usar

directamente o crear una nueva imagen a partir de ellas para añadirles alguna personalización adicional, según

sea el propósito deseado.

Es posible construir imágenes propias, adaptadas a las necesidades particulares de la aplicación que se desplegará

en contenedores. Para ello, es necesario crear un archivo de texto Dockerfile que, a modo de receta y con una

sintaxis sencilla, contenga la descripción e instrucciones para automatizar la creación de la imagen. La ventaja

del uso de los ficheros Dockerfile es que permite automatizar el proceso de creación de imágenes e ir

modificándolo según se precise. Por tanto, es posible adaptar el ciclo de vida de los contenedores para que

evolucione al mismo ritmo que el versionado de los servicios o aplicaciones que contienen.

El comando docker build ejecuta las instrucciones de un fichero Dockerfile línea a línea y va mostrando los

resultados en pantalla. Posteriormente se pueden consultar las imágenes creadas y almacenadas con el comando

docker images.

Las imágenes en Docker están compuestas por capas apiladas. Cada capa representa un cambio en el sistema de

archivos del contenedor y estas a su vez pueden ser compartidas entre distintas imágenes. La ventaja de las capas

es que una nueva imagen reutilizará aquellas capas que ya estuvieran almacenadas, haciendo más rápido el

proceso de construcción de imágenes y reduciendo el uso de los recursos de la máquina. Por ejemplo, cada

instrucción en un Dockerfile creará una capa en la imagen. Si se modifica el archivo Dockerfile, al volver a crear

la imagen, solo se reconstruyen las capas que hayan cambiado. Esto es parte de lo que hace que las imágenes

sean tan livianas, pequeñas y rápidas.

Con el comando docker history se puede consultar el histórico de una imagen Docker en el que se muestra todos

los comandos que se han ejecutado para crear la imagen.

Las capas de una imagen se apilan unas encima de otras. Todas, a excepción de la última, son de sólo lectura.

Cuando se crea un nuevo contenedor, se añade una capa de escritura por encima de las capas de lectura

subyacentes. Esta capa conserva cualquier cambio realizado en el contenedor en ejecución, como crear,

modificar o borrar ficheros.

Figura 3-4. Capas de una imagen

Page 70: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

48

Docker utiliza controladores ("drivers") de almacenamiento para administrar cómo las capas interactúan unas

con otras (sistemas de fichero de unión o UnionFS). Tiene disponibles varios drivers que implementan de forma

diferente la forma de almacenar y gestionar los contenedores de la máquina Docker, pero prácticamente todos

usan capas de imágenes apilables y la estrategia de copiar al escribir (CoW, Copy on Write): si una capa, incluida

la de escritura, necesita acceder a un archivo o directorio de una capa inferior dentro de la imagen, simplemente

recorrerá las capas y utilizará el archivo existente. Pero la primera vez que otra capa necesita modificar el archivo

(al construir la imagen o ejecutar el contenedor), el archivo se copia en la capa de escritura y se modifica. Desde

entonces, el fichero de la capa subyacente de lectura seguirá existiendo, pero oculto por la copia para el

contenedor. La consecuencia inmediata de esta estrategia es que los contenedores que realicen muchas

operaciones de escritura consumirán un mayor espacio. Es recomendable en estos casos, usar volúmenes Docker

(apartado 3.6.2.5), que son independientes del contenedor en ejecución.

Las capas se identifican por el digest resultante de aplicar un algoritmo de cifrado al contenido de la capa. El

formato del identificador se compone de algoritmo:digest.

Cada capa se almacena en un directorio de la máquina Docker. Para sistemas Linux, en la ruta

/var/lib/docker/<controlado de almacenamiento>/layers/ se pueden consultar las capas existentes. Los nombres

de los directorios no se corresponden con los identificadores de las capas.

3.6.2.2 Docker Hub / Store

Docker Hub es una plataforma Cloud en modalidad Software como servicio (SaaS, Software-as-a-Service) que

provee de un servicio de registro utilizado como repositorio de imágenes Docker. Aloja repositorios de imágenes

públicas aportados por la comunidad y repositorios oficiales, de software mantenido como proyectos de código

abierto, disponibles para su descarga, facilitando la compartición y el lanzamiento de aplicaciones.

En los repositorios no se alojan los Dockerfile, si no directamente las imágenes Docker. Es posible configurar

Docker Hub para que obtener los archivos Dockerfile de un repositorio de código, como GitHub o BitBucket, y

construir las imágenes de los Dockerfile de forma automática cuando se produzcan cambios en los archivos.

Docker Store, a diferencia de Docker Hub, aloja contenido publicado y mantenido por una entidad comercial,

previa validación de requisitos que otorguen garantías de calidad, confianza y soporte. En general, todo el

contenido de la comunidad públicamente disponible puede localizarse a través de Docker Hub y Docker Store,

y esto incluye imágenes oficiales.

Para poder encontrar repositorios e imágenes en Docker Hub, se puede buscar desde el portal web de Docker

Hub o usar el cliente de línea de comandos de Docker para ejecutar el comando docker search. Docker está

configurado para buscar imágenes en Docker Hub por defecto. No es necesario iniciar sesión para buscar y

descargar (comando docker pull) imágenes de Docker Hub; sin embargo, si es necesario identificarse en Docker

(comando docker login) para subir (comando docker push) una nueva imagen al repositorio.

En el desarrollo del proyecto ha sido necesario suscribirse a Docker Hub con una cuenta gratuita para crear un

repositorio privado en el que mantener las imágenes personalizadas de los servidores Web y base de datos que

apoyan el despliegue del servicio de información demográfica.

3.6.2.3 Docker Registry

Docker Registry es un repositorio de imágenes Docker privado y seguro. Se distribuye como una imagen de un

contenedor por lo que sería el equivalente a tener un Docker Hub que forma parte de la arquitectura de

contenedores desplegada, como un componente más. Será especialmente útil en situaciones que necesiten de un

control estricto del dónde se almacenan las imágenes y un sistema de distribución interno y rápido de imágenes.

3.6.2.4 Contendores Docker

Docker ejecuta procesos en contenedores aislados, que tienen su propio sistema de archivos, su propia red y su

propio árbol de procesos. Un contenedor se puede considerar en Docker como la instancia en ejecución de una

imagen Docker. Es necesario, por tanto, conseguir primero la imagen del contenedor.

El comando docker run lanza un contenedor a partir de una imagen y ejecuta el comando que se le indique.

Page 71: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

49

49

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Docker busca el nombre de la imagen especificada localmente. En el caso de que no existiera, la descarga de

Docker Hub y crea el nuevo contenedor: se asigna una capa de lectura y escritura, se crea una interfaz de red y

se asigna una dirección IP (si no se especificó ninguna opción de red en el comando de ejecución), se inicia el

contenedor y ejecuta el proceso indicado.

Un contenedor de Docker solo permanece en ejecución mientras el proceso lanzado esté en ejecución. Así pues,

al finalizar el comando /bin/bash con exit, el contenedor se detiene, pero no se elimina. Es posible ejecutarlo de

nuevo o eliminarlo (docker rm <contendor>).

El comando docker ps imprime la lista de los contenedores activos, y añadiendo la opción -a, incluye los

contenedores no iniciadas.

Con el comando docker rmi <imagen> se elimina localmente la imagen indicada, siempre y cuando no haya

ningún contenedor que la use.

3.6.2.5 Volumen de almacenamiento

Se ha explicado que cuando se crea un nuevo contenedor, Docker añade una capa de escritura vinculada al

contenedor por encima de las capas de lectura que conforman la imagen, y en el que el contenedor podría

almacenar datos; sin embargo, cuando se borra un contenedor, también lo hace su sistema de ficheros, perdiendo

cualquier información que contuviera.

Un contenedor está pensado para ser efímero, por lo que la persistencia de la información se plantea como un

reto a considerar. Para atajarlo, Docker proporciona tres opciones para externalizar la persistencia del ciclo de

vida de los contenedores: volúmenes, volúmenes conectados (bind mounts) y volúmenes temporales (tmpfs

mounts).

Figura 3-5. Tipos de volumenes

Además de mantener los datos fuera del ciclo de vida de un contenedor, estas opciones de persistencia presentan

las siguientes ventajas frente a la persistencia de datos en la capa de escritura del contenedor:

• No aumentan el tamaño de los contenedores que los usan.

• Permiten compartir información entre contenedores.

• Proporcionan un mejor rendimiento al escribir directamente sobre el sistema de fichero de la máquina

y no requerir controladores de almacenamientos para UnionFS.

Siempre que sea posible, los volúmenes deben ser la primera opción predefinida para la persistencia de los datos

generados con contenedores Docker. Internamente, un volumen de datos es un directorio especial de cuya

creación y administración se encarga Docker. En sistemas Linux, suele estar albergado en la ruta

/var/lib/docker/volumes/<volume-name> de la máquina anfitriona.

Existen multitud de drivers de volúmenes que se pueden usar, por ejemplo, para almacenar los datos en máquinas

remotas o proveedores de servicios Cloud, entre otras posibilidades.

Page 72: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

50

Con los volúmenes conectados o bind mount se usa un directorio local del sistema de archivos de la máquina

dentro de uno o más contenedores de Docker. Una de las desventajas que existen es que la administración de los

permisos en los directorios se vuelve manual y propenso a errores. Además, al no haber ninguna restricción en

cuanto al directorio que puede mapearse, la posibilidad de escribir sobre el sistema de ficheros de la máquina

anfitriona se rompe en mayor medida el aislamiento con el contenedor, pudiendo crear brechas de seguridad.

Los volúmenes temporales o tmpfs mount no ofrecen realmente una solución de persistencia para los datos ya

que son almacenados en la memoria de la máquina anfitriona y se borran igualmente al detener el contenedor.

Son una manera de montar carpetas temporales en un contenedor, útil para almacenar información sensible, de

sesiones web o contenido temporal.

3.6.2.6 Red

Docker permite crear y configurar diferentes redes para la comunicación entre los contenedores y con máquina

anfitriona, mediante línea de comandos con el comando principal docker network. Incluye varios controladores

("drivers") de red nativos, sin requerir ningún módulo extra.

Al instalar Docker, se crean automáticamente 3 redes preconfiguradas, denominadas none, host y bridge.

• none se usa cuando no se quiere que el contenedor tenga funciones de red.

• bridge es la red por defecto a la que se conectarán todos los contenedores si no se especifica otra red en

la ejecución del contenedor. Usa el direccionamiento 172.17.0.0/16.

En la instalación de Docker, automáticamente se configura en la máquina anfitriona una nueva interfaz

virtual de red, docker0, será usada para hacer la conexión puente (Linux bridge) con cada uno de

nuestros contenedores. La IP por defecto de docker0 es 172.17.0.1.

Figura 3-6. Pila de red

• host representa la red mapeada de la máquina anfitriona. Esto significa que no habrá aislamiento a nivel

de red entre la máquina anfitriona y los contenedores que corran en él. Por ejemplo, si iniciamos un

contenedor que ejecute un servidor web, será accesible desde la IP de nuestro host, sin necesidad de

exponer ningún puerto.

Un punto importante en relación a la red bridge por defecto es que Docker no soporta el descubrimiento

veth (virtual ethernet devices):

interfaz de red que actúa como un cable de conexión entre dos espacios de nombres de red. Un extremo del veth se coloca dentro del contenedor con el nombre de ethX y el otro se conecta a la red Docker.

Docker0 (Linux bridge):

Implementación virtual de un switch físico dentro del kernel de Linux.

Network namespace:

Representa una pila de red aislada con su propia colección de interfaces, rutas y reglas firewall.

Page 73: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

51

51

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

automático de servicio en ella, lo que significa que los contenedores conectados podrán comunicarse por IP y

no por el nombre del contenedor.

La configuración de las redes puede ser totalmente personalizada, y crear una topología virtual de redes

segregadas para la comunicación aislada entre contenedores que estén dentro de las mismas. Así, por ejemplo,

se podría generar una nueva red bridge, con un direccionamiento IP específico, si fuese necesario, a la que se

conecten ciertos contenedores para crear entornos aislados

Figura 3-7. Redes bridge

A diferencia de la red puente predeterminada, las redes definidas por el usuario admiten la dirección IP manual

y la asignación de subred. Además, una nueva red bridge definida incorpora un servicio de DNS interno que

resuelve nombres de contenedores en direcciones IP. Si no se especificase un direccionamiento IP a la red, el

driver IPAM nativo de Docker se lo asigna automáticamente tomando la siguiente subred disponible en el

espacio de IP privado.

No obstante, muchas aplicaciones requieren entornos de conexión específicos para efectos de seguridad o

funcionalidad que las redes nativas de Docker no cubren. Es por ello que el soporte de red es ampliable, mediante

drivers de red adicionales que soporten topologías específicas. Hay muchos proyectos enfocados en expandir el

ecosistema de redes de Docker.

Figura 3-8. Diferencia redes bridge y overlay

Page 74: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

52

Un tipo de red cuya configuración será necesaria durante el proyecto es la red overlay o superpuesta: red virtual

construida por encima de las conexiones de red existentes que conecta los contenedores distribuidos en un clúster

de máquinas. Se abordará en el apartado específico de los enjambres de nodos o swarm.

3.6.2.7 Puertos

Por defecto, los contenedores son accesibles por otros contenedores ejecutándose en la misma máquina

anfitriona y por la propia máquina sin ninguna configuración adicional. La interfaz docker0 de la máquina

simplemente enrutará las solicitudes recibidas al contenedor adecuado.

Cuando se crean imágenes o se ejecutan contenedores, existe la opción de exponer los puertos o publicarlos:

• Exponer un puerto se utiliza con fines informativos para indicar los puertos en cuestión que usa el

contenedor.

• Publicar un puerto, lo mapeará a la interfaz de la máquina anfitriona y hará que sea accesible desde el

exterior.

3.6.2.8 Comandos

La siguente figura recoge un resumen de los comandos básicos del CLI descritos en los puntos anteriores

Figura 3-9. Comandos Docker

3.6.3 Otras herramientas del ecosistema Docker

Hoy en día Docker es mucho más que un entorno de ejecución de contenedores. Al mismo tiempo que ha ido

ampliando su enfoque empresarial, se han ido asentado numerosos proyectos de código abierto alrededor del

proyecto central, dotándolo de un ecosistema vivo de herramientas, interfaces y servicios adicionales. En su

última etapa, los esfuerzos parecen estar dirigidos al despliegue sencillo, rápido y flexible de aplicaciones

distribuidas en infraestructuras y entornos Cloud. Esta evolución ha sido posible con el respaldo de gigantes de

la industria como Microsoft, Amazon u Oracle.

Otras herramientas de interés que complementan el ecosistema Docker son:

3.6.3.1 Docker Compose 

Docker Compose es una herramienta para definir y ejecutar aplicaciones multicontenedor en Docker. A partir

de un fichero central, basado en el lenguaje de marcado YAML, que describe y configura los servicios que

componen la aplicación, y un único comando se pueden iniciar los múltiples contenedores que conjuntamente

soportan una aplicación.

Docker-compose tiene la consideración de herramienta de orquestado de contenedores con la limitación de estar

Page 75: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

53

53

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

acotado su funcionamiento a una única máquina. Si se ejecutan diferentes proyectos compose en la misma

máquina, docker-compose los aísla diferenciándolos por un nombre de proyecto, que por defecto se corresponde

con el nombre del directorio base del proyecto.

Se ha ido modificando la sintaxis de los ficheros compose para soportar, con cada versión de formato, nuevas

funcionalidades y compatibilidad con las versiones actualizadas de Docker (enlace). La versión más reciente y

recomendada en la 3.X, diseñada especialmente para habilitar el uso de Compose con Docker en modo Swarm.

3.6.3.2 Docker Machine

Es un proyecto open source para automatizar la creación y administración de máquinas preparadas con Docker

en casi cualquier infraestructura, simplificando el proceso de instalación de Docker Engine de forma sustancial.

Docker Machine permite utilizar nuestro cliente CLI Docker para gestionar de forma centralizada otros Docker

Engine remotos que hayan sido configurados con esta herramienta. Se encarga también de generar los

certificados TLS para la comunicación segura con cada máquina provisionada.

Existen multitud de drivers o conectores para interactuar con máquinas de las principales plataformas de IaaS

como Amazon Web Services, Microsoft Azure, Google Compute Engine, Digital Ocean o plataformas de

virtualización de escritorio como VMware Fusion, VMware vSphere u Oracle VirtualBox (enlace). También

tiene un driver genérico para poder gestionar una máquina que ya estuviera funcionando y se quisiera gestionar

con Docker Machine.

Se suele recurrir a esta herramienta cuando es necesario gestionar un elevado número de nodos de Docker. Es

por ello que se usa habitualmente en combinación con Docker en modo Swarm para la configuración y

administración de un clúster de nodos Docker.

3.6.3.3 Docker en modo Swarm

Es la solución nativa para la gestión y orquestación de clúster de contenedores.

Ha tenido un papel destacado en el proyecto para conseguir alcanzar los objetivos planteados. Es por ello que se

le dedicará un apartado específico en el que describir más ampliamente su arquitectura y aplicación.

3.6.3.4 Docker Cloud

Docker Cloud es un servicio Web mediante el cual se pueden crear, probar, supervisar y distribuir contenedores

Docker en diversas infraestructuras. Docker Cloud no ofrece servicios de alojamiento, por lo que todos los

recursos para las máquinas que se crean han de ser suministrados por proveedores externos o por el propio

datacenter. Destaca por proveer de integración con las APIs de proveedores de Infraestructura como servicio

(IaaS, Infrastructure-as-a-Service) consolidados, facilitando la gestión de las máquinas Docker distribuidas en

diferentes infraestructuras y posibilitando la implementación de arquitecturas híbridas en combinación con

máquinas locales.

La plataforma provee de otras funcionalidades adicionales como su propio servicio de registro, funciones

automatizadas de construcción y prueba de imágenes (por ejemplo, vinculados a cambios en repositorios de

código fuente como GitHub o BitBucket) o realizae escaneos a las imágenes para verificar que están libres de

vulnerabilidades.

3.6.4 Docker en modo Swarm

Docker en modo Swarm es la forma nativa de Docker Engine para la gestión y orquestación de clústeres de

máquinas Docker distribuidas, funcionando como un enjambre ("swarms") de nodos preparados para la

ejecución de contenedores Docker, sin requerir ningún componente externo adicional.

Se basa en el proyecto de código abierto Swarmkit, que incluye un conjunto amplio de funcionalidades para la

orquestación de sistemas distribuidos (no necesariamente contenedores Docker) como el descubrimiento de

nodos, gestión del clúster, planificación de tareas y seguridad.

Page 76: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

54

3.6.4.1 Conceptos básicos

Es conveniente aclarar previamente algunos conceptos a las que se hacen referencia habitualmente cuando

Docker se activa en modo Swarm:

• Nodo (“node”)

Un nodo es una instancia de Docker Engine que participa en un Swarm. En términos prácticos, se refiere

a cada una de las máquinas que forman parte del clúster. Pueden tratarse de nodos físicos o virtualizados,

como servidores cloud o plataformas de virtualización de escritorio como VirtualBox.

• Servicio (“service”)

Un servicio es una abstracción que define las tareas, una o varias réplicas, que serán ejecutadas dentro

del clúster. En la definición del servicio se especifica la imagen en la que se basará y qué

parametrización utilizar para crear los contenedores que soportarán el servicio.

• Tarea (“task”)

Las tareas son las cargas de trabajo básicas dentro de Swarm, y son implementadas como contenedores

individuales y los comandos que ejecutan. En este sentido, al hablar de servicios, la forma correcta para

referirse a cada réplica no es contenedor sino tarea.

• Pila (“stack”)

Una pila es un conjunto de servicios que se ejecutan a la vez. Los servicios que componen el stack se

definen en un fichero en formato YAML (con extensión .yml), donde se recogen las especificaciones y

características de cada servicio.

Del mismo modo que Docker Compose define e inicia contenedores, se pueden definir y ejecutar stacks

de servicios Swarm.

En los sucesivos apartados se usará indistintamente el término "tarea de servicio" y "contendor" para referirse a

lo mismo.

3.6.4.2 Arquitectura

Docker en modo Swarm tiene una arquitectura tradicional de clúster, en la que existen nodos encargados de

gestionar el clúster, conocidos como nodos "Manager", y que también planifican las tareas entre los nodos que

las ejecutan, denominados nodos "Worker". Por defecto, los nodos Manager también desempeñan funciones de

nodo Worker, a no ser que se restringa para que sólo asuman las tareas de gestión.

Sólo los nodos Manager pueden gestionar el clúster. Si bien en caso de fallo de todos los managers del clúster

los contenedores que estuvieran en ejecución no se verán afectados y continuarán operando con normalidad, no

será posible administrar el clúster, lo que incluye la planificación de nuevas tareas. Es indispensable disponer de

varios nodos Manager para asegurar el estado global del clúster. Docker en modo Swarm proporciona alta

disponibilidad entre los nodos Manager utilizado el algoritmo de consenso Raft, con el que consigue replicar de

forma consistente el estado del clúster entre todos los nodos Manager. De esta forma si el nodo Manager que

fue elegido líder cae inesperadamente, el resto de nodos Manager podrán seleccionar cualquier otro como líder

para retomar la planificación de tareas.

De acuerdo al algoritmo, si desplegamos n nodos Manager, se requiere un quórum de n/2+1 nodos Manager

para elegir al líder, con una tolerancia a fallos de (n-1)/2 nodos Manager. Por lo general, se recomienda

disponer de un número impar de nodos Manager, pero no demasiados a fin de no saturar el clúster con

actividades de control y penalizar en rendimiento. Las buenas prácticas consideran como idóneos entre tres,

cinco o siete nodos Manager.

3.6.4.3 Características

Docker en modo Swarm integra funcionalidades propias de la orquestación y planificación de servicios en los

nodos de un clúster de contenedores, que ayudan a maximizar la disponibilidad de las tareas, al mismo tiempo

Page 77: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

55

55

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

que optimiza los recursos disponibles. La automatización conseguida se hace especialmente relevante en los

casos de servicios con altos requerimientos de escalado, difícilmente administrables de forma manual.

A continuación, se hace describen las principales características incorporadas en Docker en relación a la gestión

de clúster de nodos:

Integración en Docker Engine:

Toda la gestión del swarm de nodos Docker y despliegue de los servicios se puede realizar desde el cliente CLI

del propio Docker Engine.

Diseño dinámico:

Dependiendo de las circunstancias del swarm en un momento determinado, los nodos del clúster pueden

promocionar o degradar su rol en tiempo de ejecución desde un nodo Manager. Así, se adapta el clúster para

hacer más tolerante a fallos durante una demanda puntual, pudiendo volver a restablecer el clúster pasado la

ventana crítica.

Escalado:

Para cada servicio se puede declarar el número de tareas a ejecutar. La decisión sobre qué nodo del clúster

ejecutar una nueva tarea están regidas según la estrategia de planificación elegida (actualmente, sólo soporta la

estrategia denominada spread, basada en la disponibilidad de recursos). También provee mecanismos de control

con los restringir o reservar recursos a las tareas, e influir sobre el planificador conforme a atributos o etiquetas

asignados a los nodos. En caso de conflicto, las restricciones de recursos siempre prevalecerán sobre las

preferencias establecidas.

Tolerancia a fallos:

El nodo Manager está continuamente monitorizando el estado del clúster con la intención de conciliar el estado

vigente con el deseado (propiedad “desired state reconciliation”), según el número de réplicas que se haya

indicado en la definición de los servicios. De esta forma, si algún componente del clúster falla, sea una tarea

individual o un nodo completo, el modo Swarm intentará restaurar el estado deseado, recreando todas las

tareas afectadas en los nodos restantes.

Redes multi-nodos:

Enfocado a servicios, Docker proporciona funcionalidades de red avanzadas para la creación de redes virtuales

superpuestas (“overlay”), basadas en la tecnología VXLAN [22], que abstraen las topologías subyacentes y

comunican los contenedores de un servicio ejecutados en nodos distribuidos, desacoplándolo de la red física.

Básicamente, VXLAN usa una técnica de encapsulamiento que envuelve tramas de nivel 2 en datagramas UDP

de capa 4, y las envía por redes IP.

Según los requisitos de la aplicación, se pueden crear tantas redes como sean necesarios. Los contenedores que

se unan a la red podrán comunicarse, independientemente del nodo en que estén desplegados. El alcance para

estas redes siempre será de todo el clúster, aunque un nodo no tendrá acceso a la red hasta que se ejecute en el

nodo al menos una de las tareas de un servicio vinculado a la red en cuestión.

Por defecto, cuando se inicia un clúster de Swarm, se crean automáticamente dos nuevas redes en todos los

nodos del clúster. Una de ella es la red overlay por defecto ingress de Docker Swarm y la otra es una red de tipo

puente docker_gwbridge que conecta las redes overlay con una interfaz física local para puentear la

comunicación con el exterior, y funcionando a modo de gateway interno dentro del clúster. Los flujos de tráfico

de contenedor a contenedor no pasan por este puente.

Gracias al proyecto libNetwork, Docker puede extenderse mediante plugins de drivers de red para soportar un

amplio rango de tecnologías de red, como VXLAN, IPVLAN o MACVLAN, y adaptarlo a los requisitos de las

aplicaciones y a diferentes entornos de red. Actualmente Docker en modo Swarm solo es compatible con el

driver integrado de redes overlay.

Page 78: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

56

Descubrimiento de servicios:

Docker distribuye por balanceo de carga las solicitudes internas de un servicio a otro servicio asignándoles una

dirección IP virtual (VIP). Por defecto, cuando se vincula un servicio a una red, los nodos Managers asignan al

servicio una IP virtual. Adicionalmente, aprovechando los servidores DNS embebidos de cada Docker Engine,

es posible resolver internamente los nombres de servicios y contenedores desplegados en el clúster, siempre y

cuando la consulta provenga de un contenedor conectado a la misma red del servicio o contenedor solicitado.

La secuencia de resolución sería la siguiente:

• Cada tarea tiene un "DNS resolver" que envía consultas DNS a Docker Engine, que actúa como servidor

DNS.

• Docker Engine comprueba si la petición DNS se corresponde con una tarea o servicio en cada red a la

que está conectado el contenedor solicitante.

• Si la encuentra, Docker Engine busca la dirección IP que coincida con el nombre de la tarea o servicio

en su almacén de clave-valor y devuelve la IP o IP virtual (VIP) del servicio al solicitante.

• Si no lo encuentra, Docker Engine envía la petición DNS al servidor DNS por defecto (lo interpreta

como una consulta DNS externa).

Figura 3-10. Descubrimiento de servicios

Balanceo de carga:

Para apoyar al descubrimiento interno de servicios, Docker usa una función de balanceo de carga de tráfico

integrada en el kernel de Linux, IP Virtual Server (IPVS). Esta función se activa automáticamente cuando se

crea un servicio, al que, como se ha comentado, se le asigna una IP virtual (VIP) [23]. Por defecto, cuando

Docker Engine resuelve la VIP de un servicio consultado, se encarga de balancear el tráfico enviado a esa IP

virtual entre todos los contenedores sanos de ese servicio en la red.

Existe la opción de configurar el servidor DNS de Docker para que resuelva las solicitudes en modo round-robin

[24], sin que sea necesario crear una VIP para cada servicio; el servidor resuelve el nombre del servicio de forma

rotativa a las IPs de las tareas individuales que lo componen.

Figura 3-11. Secuencia de balanceo de carga

Page 79: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

57

57

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Por otro lado, el modo Swarm utiliza el sistema de balanceo de capa 4 (capa de transporte) para exponer servicios

hacia el exterior del clúster cuando se crea o actualiza el servicio. Si se publica un puerto de un servicio, se

publica en todos los nodos del clúster. Docker utiliza su propiedad "routing mesh", que combina las tecnologías

IPVS e iptables del kernel, para dirigir las solicitudes externas a las tareas que constituyen el servicio a través de

la red overlay ingress. Así, los clientes externos, como por ejemplo un balanceador de carga cloud, pueden

acceder al servicio por el puerto publicado desde cualquier nodo del clúster, incluso si la petición llegase a un

nodo que no está ejecutando ninguna tarea del servicio. Routing mesh permite abstraerse del número y

distribución de los contenedores que soportan el servicio; Docker se encarga automáticamente de la compleja

capa de gestión de la arquitectura de red subyacente y el balanceo de carga, sin que se convierta más en una

preocupación para poder escalar los servicios.

Figura 3-12. Propiedad routing mesh

Seguridad por defecto:

Docker en modo Swarm implementa mecanismos para garantizar la seguridad del tráfico de control y gestión

en todas las fases del ciclo de vida de la orquestación: inicio de confianza del clúster, adhesión segura y

autorizada de nuevos nodos, gestión de identidad de los nodos, almacenamiento e intercambio de información

autenticada y cifrada.

Teniendo en mente los mecanismos de seguridad mencionados, la secuencia de creación del swarm sería:

• El nodo Manager designado genera una nueva Autoridad de Certificación raíz (CA) para distribuir

certificados entre los nodos que se vayan añadiendo al swarm y así disponer de un canal de

comunicación TLS cifrado y con autenticación mutua de nodos. Si se prefiere, Docker da la posibilidad

de usar una CA raíz externa.

• También se generan dos tokens para el ingreso de nuevos nodos al swarm, uno para nodos Managers y

otro para Workers, que incluyen un hash del certificado de la CA raíz junto con una clave generada

aleatoriamente. Los nuevos nodos usarán el hash para validar el certificado de la CA raíz contra el

Manager, y el Manager usará la clave para confirmar que es el nodo que solicita incorporarse al swarm

es válido.

Figura 3-13. Token de anexión al Swarm

Page 80: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

58

• Una vez añadidos, el Manager emite un certificado para el nuevo nodo que lo identifica.

• Los nodos del swarm usan sus certificados para establecer comunicaciones mutuamente autenticadas.

Para los datos en tránsito entre contenedores de distintos nodos o con clientes externos, se puede cifrar el tráfico

utilizando túneles IPSec. Se habilita el cifrado indicando el parámetro --opt encrypted al crear una red overlay.

Entonces, Docker crea túneles IPSEC entre todos los nodos donde haya planificadas tareas de servicios

conectados a la red. El nodo Manager también regenera periódicamente claves simétricas para IPSec y las

distribuye a todos los nodos del clúster.

Actualizaciones continuas ("rolling updates"):

Con el modo Swarm se puede gestionar y especificar la estrategia de actualización de los servicios, tanto en el

momento de la creación del servicio como posteriormente. Por ejemplo, si la imagen de un servicio se ha

actualizado o cambia, el nodo Manager del swarm puede actualizar las tareas de un servicio, fijando la

secuencialidad o el paralelismo de la actualización y el retraso entre actualizaciones que eviten interrupciones

en el servicio. De esta forma, Docker actualizará la configuración del servicio, deteniendo las tareas

desactualizadas y creando las nuevas que coincidan con la configuración deseada, sin la necesidad de reiniciar

el servicio.

3.6.4.4 Componentes adicionales

En el anterior apartado se han enunciado las características principales inherentes al uso de Docker en modo

Swarm. Existen otros componentes o propiedades relacionados con esta modalidad de funcionamiento que se

han utilizado en el proyecto. Se introducen a continuación para facilitar la comprensión de su uso cuando se

describa en el capítulo de trabajo realizado.

Secrets:

Cuando, a efectos de configuración, es necesario compartir con los contenedores de Docker datos sensibles

desde el punto de vista de la seguridad como contraseñas, certificados, claves privadas o cualquier otra

información de acceso restringido se solía recurrir a variables de entorno que se declaraban en el momento

de la ejecución de los contenedores e incluso incrustados en un fichero Dockerfile. Sin embargo, esta

práctica no es segura. Esa información estará expuesta al examinar las propiedades del contenedor, con el

consecuente riesgo de seguridad que ello supone.

Docker Secrets es una funcionalidad que permite la gestión centralizada datos sensibles, secrets, para cifrarlos

y distribuirlos entre las tareas de los servicios a los que explícitamente se les ha otorgado acceso.

Al añadir un nuevo secreto al swarm, con el comando docker secret create, Docker envía el secreto al nodo

Manager a través de una conexión TLS mutuamente autenticada, haciendo uso de la CA integrada que se creó

automáticamente en el inicio del swarm. Los secretos se almacenan cifrados en el log Raft intercambiado entre

todos los nodos Manager; por tanto, solo los nodos Manager tienen acceso a todos los secretos almacenados.

Si un servicio, nuevo o en ejecución, recibe el permiso de acceder a un secreto, el nodo Manager se encarga de

enviar el secreto a la tarea de servicio a través de la conexión TLS mutuamente autenticada ya establecida

exclusivamente a los nodos que ejecutarán el servicio en particular. Es decir, las tareas y los nodos no pueden

solicitar un secreto, sino que son emitidos por un nodo Manager como parte de la creación o actualización de

un servicio.

El secreto se monta no encriptado en un sistema de archivos en memoria dentro de las tareas del servicio

autorizado, bajo la ruta /run/secrets/<nombre_secreto>. Tan pronto como un nodo deje de ejecutar tareas de un

servicio autorizado, eliminará el secreto de la memoria.

Volumen - persistencia multi-nodo con RexRay:

Por naturaleza los contenedores Docker son volátiles, es decir, los datos que se escriban tenderán a desaparecer

a la vez que lo hace el propio contenedor. Un contenedor, por tanto, no tiene almacenamiento persistente de

forma predeterminada; la información añadida a su sistema de ficheros está sujeta al ciclo de vida del contenedor.

Esta circunstancia no supone ningún problema para servicios sin estado o "stateless". Sin embargo, para los

Page 81: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

59

59

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

servicios "stateful" , como por ejemplo las bases de datos, habría que almacenar los datos en algún lugar externo

al propio contenedor, y así evitar que la información no se vea afectada cuando un contenedor necesite ser

sustituido.

Ya se vió en el apartado 3.6.2.5 que Docker ofrece la solución de montar volúmenes con el objetivo de conservar

los datos, incluso cuando se elimina el contenedor donde está montado. Sin embargo, siempre estarán vinculados

al sistema de ficheros de la máquina donde está ejecutándose el contenedor. En un entorno de clúster de nodos

Docker distribuidos que ejecuta un servicio stateful, se presenta la dificultad que los datos han de estar accesibles

independientemente del nodo en el que estén ejecutándose las tareas del servicio.

Una posible solución para paliar este problema es establecer restricciones en el servicio para que sus tareas se

desplieguen siempre en el mismo nodo sobre cuyo sistema de ficheros se presenta el volumen de persistencia.

Esta opción tiene la limitación de perder la capacidad de escalabilidad horizontal con la que asegurar la alta

disponibilidad de la persistencia de los datos ante un fallo del nodo; se restringe la tolerancia a fallos del servicio,

y por tanto de la aplicación.

Docker puede usar diferentes drivers para manejar los volúmenes [25], algunos vienen integrados y otros se

pueden instalar como plugins con los que extender el soporte de volúmenes de Docker. Para el propósito

perseguido, es necesario un driver de volumen que permita la integración con sistemas de almacenamiento

externos y sea compatible con múltiples nodos. De esta forma, será posible ejecutar bases de datos y otros

servicios stateful sin preocuparse del nodo del swarm en el que vayan a ser desplegados.

REX-Ray

REX-Ray [26] es motor de orquestación de almacenamiento para contenedores de código abierto que cubre

todas las necesidades planteadas. Con una configuración sencilla, se encarga de orquestar las tareas de

almacenamiento entre los nodos de un clúster y proporciona interoperatividad de Docker en modo Swarm con

múltiples proveedores de almacenamiento como Amazon EC2, Digital Ocean, Google Compute Engine, Azure,

e incluso VirtualBox. En el proyecto se emplearán servicios EBS de AWS para alojar la información del servicio

de base de datos relacional que utiliza la aplicación de información demográfica.

REX-Ray basa su funcionamiento en libStorage, una API de almacenamiento que se utiliza de interfaz para

garantizar la integración con plataformas de almacenamiento externas. Implementa una arquitectura

cliente/servidor en la que un servicio centralizado (controller), recibe peticiones de clientes (agents) para realizar

conjuntamente la orquestación del almacenamiento. Esta arquitectura admite varias opciones de

implementación: REX-Ray pueden desplegarse como un único proceso independiente que agrupa todos los

componentes cliente/servidor, o de forma centralizada en la que el servidor los agentes están segregados. En

instalaciones de pocos nodos es habitual emplear el modelo descentralizado, donde REX-Ray en modo

independiente se instala en cada nodo, agrupando cliente y servidor en el mismo servicio. La arquitectura

centralizada es más común y beneficiosa en clústeres de nodos de mayor escala, donde un controlador central

se encarga de coordinar todas las operaciones.

La instalación en los nodos Docker se puede realizar como un simple binario o como un plugin de volumen

Docker, que empaqueta el cliente/servidor en un contenedor. De forma predeterminada, REX-Ray trata las

solicitudes de Docker a través de un socket UNIX.

Además de integrarse con Docker y Kubernetes, REX-Ray permite la interoperación con los orquestadores de

contenedores que sean compatibles con la especificación CSI (del inglés, "Container Storage Interface"), un

estándar para el ciclo de vida de un volumen, que aspira a que las herramientas de orquestación puedan compartir

sus drivers de almacenamiento.

3.6.4.5 Otras soluciones

A lo largo del apartado se ha puesto foco en el funcionamiento de Docker en modo Swarm para desplegar clúster

de nodos Docker de manera manual e interactiva. Otras soluciones, como Docker for AWS, aprovechan los

servicios maduros que implementan los proveedores cloud para ofrecer mecanismos que automatizan la

configuración de una infraestructura de orquestación de contenedores distribuidos. Así, por ejemplo, Docker

para AWS usa Amazon CloudFormation para automatizar el despliegue y la configuración de EC2, configurar

auto-escalado, definir los roles y reglas de control de acceso IAM necesarios, provisionar otros recursos de

infraestructura relacionados con el clúster como balanceadores de cargar, y mucho más.

Page 82: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Herramientas

60

Page 83: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

61

4 TRABAJO DESARROLLADO

El desarrollo y despliegue del servicio de identificación objeto de este proyecto se ha estructurado en tres etapas

claramente diferenciadas que pueden corresponderse con la evolución de un sistema monolítico, en nuestro caso

un servicio de información demográfica, hacia una aplicación de consumo distribuido y con una arquitectura

que garantice los requisitos de intercomunicación con otros componentes, así como simplificar su despliegue y

mantenimiento:

1. Implementación funcional del servicio: mejora y ampliación de la implementación del servicio,

tomando como partida el servidor PIDS de un proyecto anterior.

2. Publicación del servicio: adaptación como servicio Web del servidor PIDS a fin de satisfacer los

requisitos de interoperatividad e integración demandados por el servicio en un entorno productivo

heterogéneo, de coexistencia con otras aplicaciones software.

3. Aprovisionamiento del entorno de ejecución: despliegue del servidor en un entorno de virtualización

basado en contenedores, aprovechando la flexibilidad, accesibilidad y capacidades computaciones

ofrecidas por servicios cloud.

En los sucesivos apartados se describen, para cada una de las fases enunciadas, los objetivos particulares a alto

nivel que se han fijado, las decisiones adoptadas para la consecución de tales objetivos, y la exposición de

aquellas actividades y partes de la programación relevantes con las que han materializado dichas decisiones.

4.1 Fase 1: implementación del servicio PIDS

4.1.1 Situación de partida

El presente proyecto toma como referencia el proyecto "Servidor demográfico basado en normas del CEN y

CORBAmed" realizado por María Ángeles Repullo López, cuyo propósito era normalizar un modelo de

información para datos demográficos, basado en estándares europeos de información sanitaria, que pudiera

usarse en el desarrollo de un servicio de información demográfica conforme a la especificación PIDS del grupo

CORBAmed. 

Los datos demográficos de referencia para el proyecto de partida están recogidos en normas del Comité técnico

251 del CEN (CEN/TC 251). Concretamente, los estándares que se utilizaron en la constitución del modelo de

información demográfica son los siguientes: 

• UNE-CEN/TS 14796:2005. Informática sanitaria. Tipos de datos. La norma define los tipos básicos de

los elementos que representan los valores de la información. 

• UNE-EN 14822-2:2005. Informática sanitaria. Componentes de información con fines generales

(GPICS). Esta norma está compuesta de 3 partes. La segunda parte establece los componentes para los

datos no clínicos, incluyendo la información demográfica. La estructura semántica de estos datos se

apoya en los tipos básicos definidos en la norma anterior.

No se seleccionaron todos los tipos a los que se hacen referencia en los estándares, tanto de los básicos como de

los GPICS, sino un conjunto suficiente para representar a una persona. La enumeración que sigue proporciona

el detalle de los tipos que se utilizaron:

• Tipos básicos (primitivos y compuestos): DV (tipo abstracto del que heredan el resto de tipos básicos

del estándar), BL (valor booleano), CS (representa un concepto codificado), CV (concepto codificado,

indicando el esquema de codificación usado), II (identificador unívoco de una entidad), INT (valor

entero), IVL_TS (intervalo de tiempo), ST (cadena de caracteres), TS (estampa de tiempo), URL

(dirección telemática).

Page 84: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

62

• Tipos CAG (Common Attribute Groups), atributos comúnmente vinculados a información

demográfica: EntityName (nombre de una entidad), EntityNamePart (cada una de las partes de un

nombre), PostalAddress (dirección postal), PostalAddressPart (cada una de las partes de una dirección

postal), Telecom (localizador telemático).

• Tipos GPICS (General Purpose Information Components): HealthcareProfessionalRole (descripción

del trabajo de personal sanitario), LanguageCommunication (idioma de comunicación),

PatientExtendedInformation (información extendida de un paciente), PatientStandardInformation

(información demográfica general de un paciente), Person (información demográfica general de una

persona), SubjectOfCarePerson (relaciona información de una persona que reciba atención sanitaria)

Cada tipo se implementó como una clase Java, de forma que las clases que representan a tipos complejos tienen

como variables a tipos básicos u otros tipos complejos. A partir de estas clases se maneja la información

demográfica sobre las personas.

Se parte también del modelo de base de datos diseñado para almacenar la información demográfica, junto con

el conjunto de clases y métodos Java que proporcionaban desde la creación de la base de datos hasta la gestión

de acceso y consulta para la recuperación de información. Sin embargo, ha sido necesario realizar algunos

cambios en el modelo, manteniendo la normalización de las tablas, por motivos que se indicarán más adelante.

En el proyecto anterior quedaron implementados algunos métodos de dos de las interfaces definidas en el

servicio de identificación de personas de CORBAmed, IdentifyPerson y ProfileAccess.

Nota: es preciso señalar que la norma relativa a los tipos de datos básicos fue anulada en 2012, en favor de un

conjunto de tipos de datos básicos desarrollado por ISO / TC 215, incluido en el modelo de referencia del

estándar UNE-EN ISO 13606. Hasta la fecha, sin embargo, los tipos básicos siguen estando basados en un

subconjunto de la norma obsoleta CEN/TS 14796, aunque en una futura revisión de la norma el enfoque será

alinearse con los tipos de datos HL7.

Si bien una evolución lógica hubiera sido adoptar el modelo de datos al modelo de información recogido en el

estándar 13606-1:2013, se ha mantenido el mismo modelo de datos que en el proyecto inicial al no estar

contenido en el alcance del proyecto. Los objetivos actuales están orientados a mejorar y ampliar la

funcionalidad del servicio original, extender la interfaz de acceso y consumo como servicio Web, quedando

como requisito secundario, aunque deseable, la actualización del modelo de datos.

Figura 4-1. ISO 13606-1:2013: Modelo de referencia

Page 85: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

63

63

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Por otro lado, ya se había comentado que la especificación del PIDS de CORBAmed no establecía ninguna

restricción en cuanto al modelo de datos empleado. Con la decisión tomada de mantener el mismo modelo de

datos y teniendo en mente el esquema conceptual de federación de dominios de los servicios PIDS, el presente

proyecto se correspondería con la implementación de un servicio de identificación dentro de un dominio de

identificación local. De esta forma, el actual desarrollo podría seguir utilizándose como referencia en otros

proyectos que profundicen en la federación de dominios o la integración entre sistemas de información clínicos.

En cualquier caso, aprovechando que las variaciones de los tipos primitivos de 13606-1:2013 con respecto a su

predecesora no son significativas, esta consideración quedará recogida como posible línea de continuación o

mejora para la aplicación. 

4.1.2 Objetivos

Los objetivos particulares que se marcan en esta fase están dirigidos a:

Migración del sistema de gestión de base de datos, con capacidades de operar en un entorno productivo.

• Optimización del desarrollo para rebajar el nivel de acoplamiento entre el código y el modelo de datos

demográfico, a fin de permitir la reutilización de los componentes funcionales del servidor con

independencia del modelo de datos seleccionado.

• Incremento de la profundidad de acceso a la información demográfica contenida en la base de datos, de

forma que las búsquedas de candidatos o las consultas y actualizaciones de perfiles se puedan realizar

a partir de atributos de más bajo nivel.

• Ampliación de la funcionalidad del servidor PIDS, con la implementación del método

update_and_clear_traits() de la interfaz ProfileAccess.

Alineados con los anteriores objetivos planteados, se han realizado varias modificaciones en la implementación

del servicio original, así como la adición de nuevas funcionalidades. A continuación, se detallan cada una de las

acciones y cambios llevados a cabo para la consecución de dichos objetivos:

4.1.3 Migración del sistema de gestión de la base de datos

El proyecto inicial había usado Microsoft Access como gestor de base de datos. Fue un primer requisito del

proyecto reemplazarla por otro sistema de mayor potencial, que dispusiera de capacidades avanzadas que

permitieran al servicio operar en un escenario con altas cargas de datos o de acceso concurrente, similar a los

demandados en un entorno profesional, y que no limitara su funcionamiento a sistemas operativos de Microsoft.

La justificación de la selección de PostgreSQL como gestor de base de datos fue tratado en el capítulo 3.

En una primera iteración del proyecto, el entorno de desarrollo se conforma localmente sobre una máquina

virtual Linux. En ella se instala y configura PostgreSQL para ejecutarlo como un proceso más de la máquina.

Inicialmente, la importación de la estructura y datos a PostgreSQL no constituye ningún problema, dado que el

proyecto anterior incluye clases, DB_Manager y DB_Factory, con todos los métodos necesarios para la

interacción con la base de datos, creación de las tablas e inicialización con datos de prueba desde sentencias

SQL estándar. Una vez instalado PostgreSQL, tan sólo es necesario modificar los parámetros de acceso que

estaban configurados, como credenciales, nombre de la base de datos, ruta de conexión, e invocar los métodos

de creación de la estructura de tablas de la base de datos y registro de datos iniciales. Para posteriores

restauraciones y pruebas, se parte de respaldos de seguridad que se hacen periódicamente a la base de datos,

pudiendo prescindir del código anterior.

La migración de la base de datos no tuvo ningún impacto sobre el código funcional del servicio. Como se verá

más adelante, todo el código correspondiente a la interacción con la base de datos se reemplaza completamente,

aunque por motivos ajenos a la migración. No obstante, ha habido que aplicar modificaciones menores en la

estructura de la base de datos. Entre los cambios más destacados se encuentran:

• Cambio las propiedades de algunos atributos de las tablas entitynamepart, postaladdresspart y

telecomuse para que admitan un valor por defecto. En la implementación del método

update_and_clear_traits(), la actualización de los tipos a los que pertenecen esos atributos solo ha sido

posible mediante la combinación de varias sentencias en una misma transacción. Al tratarse de atributos

Page 86: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

64

también declarados como NOT NULL, deben tener un valor registrado durante el proceso de

actualización.

• Adición de un nuevo índice en la tabla EntityName. Se pueden dar casos en los que deban registrarse

diferentes atributos del tipo EntityName para una misma persona. Conforme a la anterior estructura de

la tabla, no había forma de indexar la búsqueda por un registro particular, obligando a devolver en una

consulta todos los registros EntityName que existieran para una persona. Este nuevo índice pretende

representar la preferencia de una persona en cuanto a los nombres que tiene asociados a su identidad.

• Actualización de las restricciones ("constraits") de las tablas para mantener la integridad de la base de

datos en las acciones de actualización y borrado.

• Normalización de tabla postaladdress, dividiendo la tabla en postaladdress y postaluse.

La conexión a la base de datos desde la aplicación Java requiere de controlador JDBC (Java Database

Connectivity). El controlador proporciona una implementación razonablemente completa de la especificación

JDBC además de algunas extensiones específicas de PostgreSQL. Para su funcionamiento, basta con incluirlo

en al classpath para la aplicación.

Como dato adicional, muchas de las tareas de gestión de la base de datos, como copias de seguridad, gestión de

usuarios y permisos de acceso, pruebas de consultas SQL, edición de las propiedades de tablas o la revisión de

los datos registrados, se realizaron desde la interfaz gráfica pgAdmin III, que es compatible con todas las

características de PostgreSQL.

Figura 4-2. Interfaz pgAdmin III

4.1.4 Transformación de la gestión de sentencias

No hay que olvidar que el proyecto estaba inicialmente enmarcado en el propósito global de establecer un

modelo de integración de dominios de identificación federados, en el que cada dominio podría emplear distintos

modelos de información. Es por ello que se considera un requisito clave diseñar el servicio PIDS reduciendo el

acoplamiento general de los componentes del servicio y, muy particularmente, entre la lógica funcional y el

modelo de datos demográficos seleccionado. Mantener el acoplamiento lo más bajo posible entre ambas capas

redundará en una simplificación del mantenimiento, una mejora considerable en la detección y corrección de

errores, y especialmente en la reutilización de la lógica de negocio, dotando modularidad y portabilidad a la

aplicación.

Originalmente, todo el tratamiento de la base de datos se había implementado trabajando con la API JDBC

directamente, haciendo que las operaciones estuvieran integradas en clases Java con el código de la aplicación.

Page 87: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

65

65

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Además, se generaron métodos de consulta estrechamente vinculados a cada tipo de dato que se necesitaba

recuperar. Al final, todo deriva en la generación de una gran cantidad de código, con duplicidades y

perfectamente acoplado a la lógica de negocio de la aplicación. Cualquier cambio en el modelo de datos o en las

consultas obligaba a localizar en el código todas las partes implicadas en el cambio, y editarlo, con el consecuente

riesgo de modificar accidentalmente alguna parte no afectada o no tener en consideración todas las dependencias

existentes con el cambio. Posteriormente, era necesario recompilar el proyecto por completo para asegurarse

que no hay errores no contemplados. Una práctica recomendada de la programación por capas consiste

precisamente en separar la lógica de negocio de la capa de datos, apuntando a mejorar la mantenibilidad del

código y compartir totalmente el modelo de datos entre todas las versiones de la aplicación.

Todo lo anterior motivó la decisión de volver a reformular todo el código relacionado con la gestión de las

operaciones de base de datos, insertando una capa de persistencia implementada con el framework MyBatis,

tratado en el apartado 3.3. Esta capa mantiene la aplicación Java independiente de la lógica de persistencia y la

tecnología de la base de datos subyacente. MyBatis se encarga de mapear los objetos, en el ámbito de la

aplicación, a los datos que hay que persistir en la base de datos utilizando ficheros XML denominados mappers.

4.1.4.1 Uso del framework de persistencia MyBatis

MyBatis representa el cambio más significativo realizado en el proyecto sobre la implementación del servicio.

Su utilización conlleva dos aportaciones fundamentales sobre el proyecto: la simplificación del código de acceso

a la base de datos y persistencia de los objetos Java, y el mayor desacople entre el código de la base de datos y

el código de la aplicación.

Para usar MyBatis sólo es necesario incluir el fichero mybatis-x.x.x.jar correspondiente a la versión a utilizar en

el classpath.

La ejecución de SQL y el mapeo objeto-relacional se realiza integrando entre sí los componentes principales de

MyBatis que se describen en la siguiente tabla:

Componente / fichero de configuración Descripción

Fichero de configuración MyBatis SqlMapConfig.xml

Fichero XML que configura el comportamiento de MyBatis.

Es un archivo que explica detalles como los parámetros de

conexión a la base de datos, la ruta de los ficheros de mapeo, cómo

deben controlarse las transacciones, la configuración global de

MyBatis, etc.

org.apache.ibatis.session.

SqlSessionFactoryBuilder

Lee el fichero de configuración y crea una instancia de

SqlSessionFactory.

Esta clase puede desecharse una vez creada la SqlSessionFactory.

No tiene sentido reutilizarlo, por lo que ámbito y ciclo de vida es el

método.

org.apache.ibatis.session. SqlSessionFactory

Crea una instancia de SqlSession.

Es recomendable tener sólo una instancia de esta clase que perdure

durante toda la ejecución de la aplicación, por lo que su ámbito es

la aplicación.

org.apache.ibatis.session. SqlSession

Contiene todos los métodos necesarios para ejecutar sentencias

SQL contra la base de datos y controlar las transacciones.

Las instancias de esta clase no son thread safe, por lo que no deben

compartirse. Cada hilo de ejecución debería tener su propia

instancia de SqlSession. El ámbito adecuado es el de petición

(request).

Ficheros mappers Ficheros XML que contienen las definiciones de mapeo (SQL

mapped statements)

Tabla 4–1. Componentes MyBatis

Page 88: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

66

Flujo de ejecución

Con una solicitud de ejecución de cualquier sentencia, se desencadena un flujo de trabajo en el que participan

los componentes principales de MyBatis para acceder a la base de datos. Según el momento en que intervienen

los componentes, el flujo de actividad puede dividirse en dos tipos: las actividades que se realizan una única vez

al inicio de la aplicación y las que se ejecutan con cada sentencia. El siguiente diagrama reproduce todo este

proceso:

Figura 4-3. Flujo de actividad de los componentes MyBatis

En el arranque del servicio PIDS (1), se carga el fichero de propiedades que contiene información relevante para

la configuración de la aplicación como las rutas a los ficheros de configuración de MyBatis, otros ficheros de

propiedades o los valores de ciertas propiedades que se usan para la configuración del DataSource. Las

propiedades de este fichero estarán disponibles a lo largo del ciclo de vida de la aplicación. Inmediatamente, a

partir de la clase de utilidad Resources que proporciona MyBatis con métodos que simplifican la carga de

recursos desde el classpath u otras ubicaciones, se recupera la ruta del fichero de configuración de MyBatis (2)

que se utiliza en la instanciación del SqlSessionFactory válido durante la ejecución de la aplicación (3).

MapLoader.java

// …

private static SqlSessionFactory sqlSessionFactory=null; static{

try{ Reader reader=Resources.getResourceAsReader(getMapConfigPath());

sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); }catch(IOException e){} }

// …

Posteriormente, con cada operación que la aplicación requiera realizar sobre la base de datos (4), se crea una

instancia SqlSession a partir del SqlSessionFactory construido en el inicio de la aplicación (5)(6). Se usan los

métodos de SqlSession (7) para invocar la sentencia SQL declarada en los ficheros XML de mapeo a partir del

Page 89: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

67

67

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

identificador dentro del namespace que se utiliza para el mapped statement indicado (8). El commit y rollback

de la transacción son métodos de SqlSession que deben llamarse desde la aplicación. Igualmente, es importante

cerrar la SqlSession una vez se haya obtenido la respuesta de la sentencia para asegurarse que los recursos de la

base de datos se liberan correctamente.

Con MyBatis se simplifica la programación frente a JDBC, reduciendo el código para las sentencias de tipo

SELECT, DELETE y UPDATE de tipos básicos a prácticamente una línea de código. Así mismo, favorece que

la lógica del servicio se constituya como un bloque software modular, que hace posible su reutilización y

portabilidad, aún en caso de sustitución completa del modelo de datos de la capa subyacente.

Queries.java

// … public List SelectTrait(String consulta, DV ind){ List select=session.selectList(consulta, ind); return select; } public int DeleteTrait(String consulta, DV ind){ int cont=0; cont=session.delete(consulta, ind); if(cont==0) System.out.println("** No se han producido cambios **"); session.commit(); return cont; } // …

Como se puede comprobar en el extracto de código anterior, dado que no se puede saber con antelación el

número de objetos que se espera recibir tras una consulta, los resultados de las sentencias SELECT se recogen

siempre en un objeto java.util.List.

Nota: no ha sido posible confeccionar esa envoltura de abstracción a las sentencias UPDATE de algunos tipos

complejos como EntityName, EntityNamePart, PostalAdress, PostalAddressPart, Language, Telecom,

etc., para los cuales hay que implementar cierta lógica en la aplicación y la creación de métodos específicos.

No se ha estudiado la posibilidad de resolver este inconveniente mediante procedimientos almacenados,

también soportados por MyBatis. No obstante, con el objetivo de homogeneizar el modo de invocación de todos

los métodos de actualización en tiempo de ejecución, requiriendo para ello únicamente el identificador de la

sentencia, se utiliza el patrón Reflection [27] sobre estos métodos.

Configuración

El primer paso sería la configuración de MyBatis mediante el fichero SqlMapConfig.xml, aunque igualmente se

hubiera podido configurar desde la propia aplicación Java.

MyBatis proporciona una multitud de parámetros [28] que pueden personalizarse en función de las necesidades

particulares de la aplicación. Existe una configuración predeterminada para cada parámetro de configuración

que suele ser adecuada en la mayoría de los casos.

Page 90: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

68

SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE configuration

PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN"

"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<properties resource="<Path_to>/ResourceData.properties"/>

<!-- … -->

<environments default="development">

<environment id="development">

<transactionManager type="JDBC"/>

<dataSource type="POOLED">

<property value="${driver}" name="driver"/>

<property value="${url}" name="url"/>

<property value="${username}" name="username"/>

<property value="${password}" name="password"/>

</dataSource>

</environment>

</environments>

<mappers>

<mapper resource="pid/pfc/service/maps/CS.xml"/>

<mapper resource="pid/pfc/service/maps/CV.xml"/>

<mapper resource="pid/pfc/service/maps/ST.xml"/>

<mapper resource="pid/pfc/service/maps/URL.xml"/>

<mapper resource="pid/pfc/service/maps/EntityNamePart.xml"/>

<mapper resource="pid/pfc/service/maps/EntityName.xml"/>

<mapper resource="pid/pfc/service/maps/PostalAddress.xml"/>

<!-- … -->

</mappers>

</configuration>

Las secciones más importantes son:

• El elemento environments específica la identificación del entorno por defecto. Pueden configurarse

varios entornos que usen las mismas sentencias mapped statements.

• El elemento enviroment se identifica con un nombre. En este caso, "development".

• La configuración del transactionManager se establece a JDBC, lo que significa que se delega en la

aplicación la gestión de las operaciones transaccionales (commit, rollback, etc.).

• El dataSource se configura como POOLED, es decir, se utilizará un pool de conexiones para que no

sea necesario crear una conexión cada vez que se requiera interactuar con la base de datos. Los valores

de los parámetros de conexión (driver, ruta de conexión, usuario y password) del DataSource se

configuran dinámicamente a partir del fichero de propiedades ResourceData.properties indicado en el

elemento properties.

• Dentro de la sección de mappers se especifican los ficheros XML de mapeo. Se ha considera crear un

fichero por cada tipo de datos para mayor claridad, aunque todos se encuentran en el mismo

namespace.

Aunque podría seleccionarse una ubicación arbitraria, para la locación de los ficheros de mapeo se han

seguido las recomendaciones de MyBatis, en las que los namespaces de los ficheros se deben

corresponder con los nombres de los paquetes Java. De esta forma se asegura la usabilidad del código.

Page 91: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

69

69

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Mapped Statements

En el proyecto se toma la decisión de externalizar las sentencias a ficheros a ficheros XML de mapeo (XML

mappers). En estos ficheros es donde se vinculan los objetos Java con sentencias SQL mediante la definición de

mapped statements. Los mapped statements se corresponden con los elementos XML que contienen las

sentencias de tipo SELECT, INSERT, DELETE y UPDATE. Todos los statements deben tener un identificador

único dentro del namespace del mapper. Para ejecutar cualquiera de estas sentencias es necesario pasar la

identificación apropiada desde los métodos en la aplicación Java, además del objeto de parámetro de entrada.

En la mayoría de los casos y dependiendo del tipo de statement, el parámetro de entrada será el JavaBean que

representa un tipo de dato demográfico, o un objeto con los índices de búsqueda particulares.

MyBatis es capaz de determinar automáticamente el TypeHandler con el que mapear los parámetros de consulta

a partir de las variables de los objetos de entrada pasados en el método de invocación del statement.

Para cada tipo de statement, MyBatis provee de varios atributos, relacionados con el funcionamiento de la caché,

el tiempo máximo de respuesta, los tipos de los parámetros de entrada y devueltos, etc., con los que configurar

su comportamiento. Los valores por defecto para los atributos de los insert, delete y update statements son

suficientes; mientras que los más habituales en los select statements son los atributos resultType, con el nombre

completamente cualificado (si no se ha especificado un TypeAlias) del tipo devuelto, o resultMap, para resolver

mapeos de mayor complejidad.

Los mapped statements declarados en el proyecto se organizan en base a los siguientes criterios:

• Cada tipo de dato del modelo de información demográfica, sea simple o complejo, tiene su propio

fichero XML mapper con el mismo nombre del tipo que representa.

• Todos los mappers pertenecen al mismo namespace

(pid.pfc.service.mappers.BeanMapper), así los ficheros quedan ubicados en la misma

ruta.

• Cada fichero agrupa las sentencias en varios bloques, no siendo estrictamente necesario que existan en

todos los ficheros:

o SELECT: conjunto de las sentencias para la recuperación de la información a partir de índices

de identificación.

o DELETE: conjunto de las sentencias para el borrado de información a partir de índices de

identificación.

o UPDATE: conjunto de sentencias para la actualización de información a partir índices de

identificación. Empleados especialmente para los tipos simples.

o INSERT: conjunto de sentencias para la inserción de lo valores de los índices de identificación.

Usados como apoyo en determinadas operaciones de actualización.

o IDENTIFYPERSON: conjunto de las sentencias para la recuperación del identificador de

persona a partir de datos demográficos.

o CHECK: conjunto de las sentencias opcionales para la comprobación de la integridad de

algunas tablas relacionales.

o HELP: conjunto de las sentencias opcionales de apoyo a determinadas operaciones o para la

recuperación de información adicional sobre las tablas.

• Cada fichero contiene los statements referentes a los atributos de una persona que se correspondan con

el tipo de datos que representa el fichero.

• La nomenclatura usada para la identificación de cada statement es: get/del/up/in/get_personid[upper

traitname]<atribute trait>

El fichero Auxiliary.xml contiene algunas sentencias no directamente relacionadas con los datos demográficos,

pero necesarias en los métodos de las interfaces del servicio PIDS, como por ejemplo para el cálculo del grado

de coincidencia en la "búsqueda de candidatos". También aloja los fragmentos de SQL que se reutilizan en varias

consultas, definidos en los elementos sql.

Page 92: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

70

Los tipos complejos de alto nivel, como EntityName o Postaladdress, se componen de propiedades de tipos

simples y otros tipos complejos. A diferencia del proyecto anterior y como se describe más adelante, el actual

servicio PIDS se diseña con el propósito de poder lanzar consultas desde atributos de más bajo nivel, como por

ejemplo actualizar el segundo apellido de una persona o consultar uno de los números de teléfonos de una

determinada finalidad. Estas relaciones entre los atributos complejos y sus elementos relacionados se

implementan mediante Selects anidadas definidas en ResultMaps. Así, por ejemplo, en el ResultMap de un trait

de tipo EntityName, la asociación con su propiedad entityNamePart, otro tipo complejo, se realiza indicando el

identificador de la select statement que se encarga de mapear los objetos EntityNamePart. Estas asociaciones

encadenadas serán recursivas para los tipos complejos, hasta llegar a tipos simples. Si bien este método es

sencillo, deriva en la ocurrencia del problema conocido como "N+1 consultas" que puede generar un impacto

considerable en el rendimiento cuando el volumen de datos es grande.

EntityName.xml

<!-- … --> <resultMap id="get-entityname-result"

type="pid.pfc.service.beans.EntityName"> <association property="entityNamePart" select="getEntityNamePart" column="{person=personid, rol=personrole, primer=priority}"/> <association property="validTime" select="getValidTimeEntityName" column="{person=personid, rol=personrole, primer=priority}"/> </resultMap> <!-- … --> <select id="getEntityName" resultMap="get-entityname-result"

resultOrdered="true"> select * from entityname where personrole=#{rol} and personid=#{person} <if test="primer != null and primer != ''">AND priority=cast(#{primer} as integer) </if> ; </select> <!-- … -->

MyBatis dispone de alternativas que resuelven el problema del N+1, como las asociaciones mediante

ResultMaps anidados en sentencias que hacen JOIN de las tablas relacionadas.

Nota: a modo de ejemplo, en el fichero Telecom.xml del proyecto está preparada una consulta basada en

ResultMaps anidados. Con este método se evita el problema de "N+1 consultas", aunque igualmente se pierde la

característica de reutilizar para las sentencias de atributos complejos aquellas que ya estuvieran diseñadas

para los sub-atributos que los componen.

Tal y como se aprecia en el ejemplo anterior, las capacidades de SQL dinámico de MyBatis se aprovecharán

principalmente para, sobre una misma consulta, recuperar un atributo de la persona o una colección de ellos, en

función de la disponibilidad o no de los índices que se hubieran aportado en la consulta.

4.1.4.2 Diseño del "árbol de traits"

Relacionado con el modelo de datos, se debe construir un documento XML con la estructura jerarquizada de los

atributos demográficos. Para el ámbito del proyecto, este documento XML se denominará "árbol de traits". El

árbol de traits cumple dos finalidades clave: establecer la sintaxis de nombrado de los atributos (la propiedad

Page 93: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

71

71

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

traitname para el objeto Trait definido en la especificación PIDS) y almacenar los identificadores de los mapped

statements asociados a cada atributo.

El nombre del trait (traitname) estará formado por subcadenas o tramos, separados por barras inclinadas, que se

corresponden con los nombres de los elementos por los que se pasa a medida que se va recorriendo la jerarquía

del árbol, de manera similar a las rutas de directorios en un sistema de ficheros. Los sub-elementos que se

correspondan con colecciones de traits, tienen un atributo atrib con los nombres separados por coma de los

índices (separados por coma) que se pueden usar para indexar esos traits.

Traits.xml

<?xml version="1.0" encoding="UTF-8"?> <PID> <!-- … --> <addr atrib="primer"> <!-- … --> <postalAddress atrib="segundo, use"> <SELECT>getPostalAddressPart</SELECT> <DELETE>delPostalAddressPart</DELETE> <UPDATE>upPostalAddressPart</UPDATE> <INSERT/> <addressLine> <!-- … --> </addressLine> <!-- … --> </postalAddress> <!-- … --> </PID>

Las reglas sintácticas que se han establecido para los traitnames son:

• El primer tramo nunca lleva índices.

• El primer tramo determina el "rol" de la persona. Los valores posibles son Patient y

HealthCareProfessional.

• Los índices están inmediatamente después del nombre del tramo.

• Los índices tienen la nomenclatura [@<nombre del índice>].

Si un traitname no contiene ningún índice para un trait cuyo elemento en el árbol tiene el atributo atrib, se

interpreta que el valor esperado es la colección completa de traits registrados.

Obviamente el orden de los tramos en el nombre del trait debe coincidir con la estructura jerárquica definida en

el árbol. Del mismo modo, si se especifica un índice en un tramo del traitname que no lo requiere o no coincide

con ninguno de los declarados en el árbol para ese tramo, la evaluación del nombre provocará una excepción en

la aplicación. Esta evaluación del traitname no tiene efecto en la búsqueda de candidatos partiendo de atributos

dados.

Page 94: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

72

En la siguiente tabla se indican algunos ejemplos que se pueden extraer del fragmento del árbol de traits anterior

para terminar de entender la construcción del traitname:

TraitName Descripción

/Patient/addr Conjunto de todos los

PostalAddress existentes para una

persona

/Patient/addr[@primer=1]/postalAddress[@segundo=3] Tercera parte (p.ej, código postal)

de la dirección preferente registrada

para una persona

/Patient/addr[@primer=1]/postalAddress Todas las partes de la dirección

preferente registrada para una

persona

/Patient/addr/postalAddress[@segundo=3] Terceras partes de todas las

direcciones registradas para una

persona

Tabla 4–2. Ejemplos descriptivos de traitnames

Esta indexación ha permitido diferenciarse del servicio PIDS desarrollado en el proyecto de partida, cuyas

consultas sólo se podían hacer para los elementos de primer nivel. En el proyecto actual se ha ampliado el

espectro consultivo y de tratamiento, especialmente útil en las actualizaciones y borrados de registros muy

concretos de la base de datos. Sin embargo, el árbol de traits constituye el punto de mayor acoplamiento entre

el código y el modelo de datos en el proyecto. Además, la sintaxis que se utiliza en el árbol debe ser conocida

en la parte cliente de la aplicación, de lo contrario no podrá formar correctamente el nombre de los traits.

Conocido el nombre del trait y el tipo de sentencia que se pretende invocar, es relativamente sencillo conseguir

el identificador del mapped statement específico. Cada elemento trait en el árbol XML está formado por

subelementos SELECT, DELETE, UPDATE, INSERT con los identificadores que reciben como parámetro los

métodos de ejecución de sentencias. No necesariamente todos los elementos tendrán identificadores para todos

los tipos de sentencias. Un subelemento adicional, IdentifyPerson, estará únicamente disponible en los elementos

que pueden ser utilizados como atributos para la búsqueda de candidatos.

En cuanto al código de la aplicación, todo lo relativo al tratamiento de los nombres de los traits, obtención de

los índices e identificadores de las sentencias, y validaciones de las expresiones se desarrolla utilizando los

métodos proporcionados en la librería XPath.

4.1.4.3 Clase Index

Los métodos para ejecutar sentencias de la clase SqlSession, en su forma más sobrecargada, sólo admiten un

objeto como parámetro de entrada para el mapeo con las sentencias SQL, además del identificador de la

sentencia. La mayoría de las consultas SELECT se han implementado para que sólo necesiten recibir los valores

de los índices usados en el mapeo de cualquier tipo de atributo. En este sentido, se ha creado la clase Index, de

tipo JavaBean, que consta de tantas propiedades como índices se utilicen en el árbol de traits. Por lo general, la

invocación de métodos de consulta solo recibe como parámetro una instancia de esta clase.

En el caso de las sentencias UPDATE el inconveniente es que, junto con los valores de los índices, el objeto

recibido como parámetro también debe contener las propiedades del atributo a actualizar, independientemente

del tipo que se trate. Se opta por hacer que la clase DV extienda a su vez la clase Index, y así conseguir "propagar"

las propiedades de los índices y sus métodos setter y getter a cada tipo de atributo.

Page 95: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

73

73

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

4.1.5 Estructura de paquetes, clases y métodos

La parte funcional del servicio PIDS se ha desarrollado con la estructura de paquetes Java que se describe en

este apartado.

• pid.pfc.service.common: contiene las clases para el manejo de los ficheros de propiedades que

almacenan pares clave-valor correspondientes a las rutas de ficheros de configuración u otras variables

relevantes para el servicio , y los carga en tiempo de ejecución para su disponibilidad a lo largo de todo

el ciclo de vida de la aplicación.

• pid.pfc.service.handler: incluye las clases encargadas del tratamiento de los traitnames, y

la construcción y evaluación de las expresiones XPath para recuperar del árbol de traits el identificador

de la sentencia relativo al trait que se hubiera indicado.

• pid.pfc.service.handler.exceptions: incluye excepciones relacionadas principalmente

con los incumplimientos de las reglas sintácticas establecidas para los traitnames.

• pid.pfc.service.loader: contiene la clase para la instanciación del SqlSessionFactory único

durante toda la ejecución de la aplicación.

Page 96: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

74

• pid.pfc.service.query: comprende la clase con los métodos para ejecutar las sentencias contra

la base de datos usando la librería MyBatis.

• pid.pfc.service.impl: se corresponden con las clases del SIB del servicio Web, que

implementan los métodos definidos en el SEI para el servicio Web generado a partir del documento

WSDL (más detalles en la próxima sección sobre la transformación del PIDS en servicio Web). En ellos

es donde se desarrolla toda la capa funcional del servicio. Estas clases e interfaces se describieron en el

apartado 3.4.1.

• pid.pfc.service.maps: ruta en la que se encuentran los fichero XML de mapeo con los mapped

statements, organizados por los tipos simples y GPICS vinculados a una persona.

Page 97: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

75

75

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

• pid.pfc.service.tree: ruta al árbol al fichero XML que representa al árbol de traits.

4.2 Fase 2: PIDS como servicio Web

No cabe duda que la innovación en el campo de la e-sanidad está ligada a la comunicación e interacción entre

los sistemas sanitarios, de diferentes instituciones, diferentes tecnologías y dispersos geográficamente, que

deben intercambiar información de forma estandarizada para proveer servicios integrados.

En el contexto de este proyecto se convierte en un requisito la implementación del PIDS como servicio Web

para dotarle de las capacidades de interoperatividad reclamadas y distribuir el servicio a través de Internet. Se

va a construir como un servicio Web basado en SOAP, usando JAX-WS como API de programación para leer

o generar los mensajes SOAP implicados en la invocación de los métodos remotos.

A pesar de contar con una implementación avanzada del PIDS, se empleará un enfoque pseudo-descendente

(contract-first) para la programación del servicio Web; es decir, el punto de partida será la definición del fichero

WSDL que, junto con los esquemas XML de los tipos de datos usados en el servicio, describe las interfaces de

operación del servicio. La complejidad de los datos intercambiados en las operaciones incentiva la necesidad de

tener un mayor control sobre las estructuras de datos más adecuadas para la invocación del servicio. Sin

embargo, se han realizado algunas personalizaciones para evitar tener que modificar el código disponible. Por

ejemplo, se han impuesto restricciones directas sobre el esquema XML para preservar la compatibilidad del tipo

timestamp con el formato ya usado en la base datos ("dd-MM-yyyy HH:mm:ss"). Este tipo de dato no está

soportado de forma predeterminada por JAXB (apartado 3.4), aunque tampoco era deseable recurrir a la

definición de una clase personalizada XMLAdapter con el que controlar el formato del dato en los procesos de

marshalling y unmarshalling. Estas condiciones en el esquema XML, derivadas de un formato existente en la

implementación del servicio, son por las que se habla de un diseño pseudo-descendente.

4.2.1 Enfoque descendente / WSDL

En este apartado se explicará en detalle el contenido del fichero WSDL definido para el servicio PIDS. En

términos generales, en el "contrato" WSDL se especifica el formato de los datos, define los mensajes

intercambiados en las operaciones del servicio y establece los requerimientos de transporte a través de la red. Lo

detalles de la estructura del documento WSDL se desarrolló en el apartado 2.2.2.4.

El elemento raíz de un documento WSDL contiene varios atributos xmlns para declarar los elementos de

namespaces, tanto los de estándares como los definidos para los tipos de datos, y asignarles un prefijo

identificativo. Con el atributo targetNamespace se establece el namespace de todos los elementos que se definan

en el documento. Sabiendo que la estructura de carpetas se genera tomando como referencia el

targetNamespace, se asigna el valor http://pfc.pid/wsdl para mantener la nomenclatura de los

paquetes de la implementación del PIDS.

Dentro del elemento <types> se añaden dos esquemas XML:

• targetNamespace http://pfc.pid/service/beans: contiene la definición en XML de los

tipos de datos usados en el modelo de información demográfica, incluyendo los tipos básicos, CAG y

GPICS.

Todos los tipos son declarados con la etiqueta <complexType> con el mismo nombre del tipo de datos

al que representan. Mantienen la jerarquía y estructura de herencia comentada en apartados anteriores:

los tipos complejos son contenedores de elementos de tipos simples u otros tipos complejos. Algunas

consideraciones para la interpretación del esquema son:

o La definición de un elemento element debe contener una propiedad name, que representa su

nombre, y una propiedad type para indicar el tipo de elemento. Podemos utilizar alguno de los

tipos predefinidos (built-in types), por ejemplo xs:string, xs:integer, o bien podemos definir

Page 98: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

76

nuevos tipos utilizando etiquetas simpleType o complexType.

o Los elementos que componen un complexType deben contener un atributo name y type. En

función de la propiedad del tipo al que representen, el atributo type puede ser alguno de los tipo

predefinidos en XML schema, por ejemplo xsd:string, o bien otro de los nuevos tipos definidos

en el propio esquema XML.

o Los componentes de un tipo que no tengan el atributo minOccurs a "0" serán interpretados

como elementos obligatorios (las propiedades de la clase Java que JAXB genere a partir del

esquema estarán anotadas como @XmlElement(required = true)).

o El atributo maxOccurs se utiliza en aquellas propiedades que, según el estándar del tipo de

datos, se correspondan con una colección de elementos de un tipo determinado.

PID.wsdl -- Types: beans

<!-- … -->

<xsd:complexType name="ST"> <xsd:complexContent> <xsd:extension base="bn:DV"> <xsd:sequence> <xsd:element name="characterString" type="xsd:string"/> <xsd:element name="charset" type="bn:CS"/> <xsd:element name="language" type="bn:CS"/> </xsd:sequence> </xsd:extension> </xsd:complexContent> </xsd:complexType>

<xsd:complexType name="EntityName"> <xsd:sequence> <xsd:element maxOccurs="unbounded" minOccurs="0" name="entityNamePart"

type="bn:EntityNamePart"/> <xsd:element name="validTime" type="bn:IVLTS"/> </xsd:sequence> </xsd:complexType>

<xsd:complexType name="EntityNamePart"> <xsd:sequence> <xsd:element name="entityNamePart" type="bn:ST"/> <xsd:element name="namePartType" type="bn:CS"/> <xsd:element name="namePartQualifier" type="bn:CS"/> </xsd:sequence> </xsd:complexType>

<!-- … -->

• targetNamespace http://pfc.pid/xsd: se corresponde con el modelo de información

demográfica de la especificación PIDS. En este esquema XML también se definen los elementos que

"envuelven" los parámetros de entrada, excepciones y valores de retorno utilizados por las operaciones

del servicio Web.

A diferencia del esquema XML de los beans, se han añadido anotaciones en línea para personalizar la

forma en la que JAXB debe representar las colecciones de elementos en los procesos de serialización y

deserialización [29].

Page 99: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

77

77

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

PID.wsdl -- Types: xsd

<!-- … --> <xsd:complexType name="Profile"> <xsd:sequence> <xsd:element maxOccurs="unbounded" minOccurs="0" name="seq"

type="axis2:Trait"> <xsd:annotation> <xsd:appinfo> <jxb:property collectionType="indexed"/> </xsd:appinfo> </xsd:annotation> </xsd:element> </xsd:sequence> </xsd:complexType>

<!-- … -->

<!-- Tipos "wrappers" de los parámetros y valores devueltos de la operación

GetProfile -->

<xsd:element name="getProfileReq"> <xsd:complexType> <xsd:sequence> <xsd:element name="PersonId" type="xsd:string"/> <xsd:element name="traitsRequested" type="axis2:SpecifiedTraits"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="getProfileRes"> <xsd:complexType> <xsd:sequence> <xsd:element name="profile" type="axis2:Profile"/> </xsd:sequence> </xsd:complexType> </xsd:element> <!-- … --> <!-- Ejemplo de elemento Fault --> <xsd:element name="duplicateTraitsFault"> <xsd:complexType> <xsd:sequence> <xsd:element name="duplicate" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <!-- … -->

La etiqueta <annotation> especifica que esa parte del esquema está destinada al software de

procesamiento de esquemas. La etiqueta <appinfo> introduce las instrucciones para la herramienta de

generación de código xjc de JAXB. En este caso, simplemente se indica que el valor resultante no deber

ser una clase java.util.List sino una propiedad array (Trait []).

Aunque esta personalización resta flexibilidad al servicio Web, ya que lo liga en cierto modo a la

tecnología que la desarrolla, se realiza con fines expositivos de las posibilidades de personalización de

JAXB. Por otro lado, aclarar que hubiese sido posible usar un fichero externo con las personalizaciones

declaradas.

Page 100: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

78

Nota: cada uno de los esquemas XML se podrían haber definido en un documento externo para luego importarlo

al WSDL indicando simplemente la localización del fichero como atributo para el elemento <schema>.

Igualmente, las personalizaciones en las vinculaciones de JAXB podrían haberse declarado en un fichero

externo, sin necesidad de modificar el esquema original, aunque se han mantenido sobre el esquema para

visualizarlas más fácilmente en el contexto del esquema al que se aplican.

Basados en los tipos de datos definidos, ahora se pueden crear la estructura de los mensajes (<message>) que

se intercambiarán en las operaciones, relativas a solicitudes, respuestas o notificación de excepciones. Cada

mensaje se compone de una o más partes, conceptualmente equivalentes a los parámetros de entrada o valores

devueltos en la invocación de una función. El atributo element de cada parte del mensaje especifica el tipo de

dato de dichos parámetros.

PID.wsdl -- Messages

<!-- … -->

<wsdl:message name="getProfileRequest"> <wsdl:part name="param" element="ns:getProfileReq"/> </wsdl:message> <wsdl:message name="getProfileResponse"> <wsdl:part name="result" element="ns:getProfileRes"/> </wsdl:message> <wsdl:message name="InvalidIdFaultMessage"> <wsdl:part name="part1" element="ns:invalidIdFault"/> </wsdl:message>

<!-- … -->

El siguiente paso es describir las interfaces del servicio Web mediante las operaciones contenidas en los

elementos <portType>. Se declaran dos elementos portType, IdentifyPersonPortType y

ProfileAccessPortType, uno por cada interfaz del servicio PIDS dentro del alcance del proyecto, en los que

se incluyen tantas operaciones como métodos se vayan a implementar de la interfaz. Los elementos

<operation> se identifican con el mismo nombre del método que representan, y según el tipo de operación,

tendrá elementos <input> y/o <output> con los mensajes de entrada y salida que se intercambiarán. En el

proyecto todas las operaciones son del tipo request-response. Los elementos <fault> se corresponden con

los mensajes para la comunicación de situaciones excepcionales.

PID.wsdl -- PortType: IdentifyPerson

<!-- … --> <wsdl:portType name="IdentifyPersonPortType"> <wsdl:operation name="findCandidates"> <wsdl:input message="tns:findCandidatesRequest"/> <wsdl:output message="tns:findCandidatesResponse"/> <wsdl:fault name="duplicateTraitsException"

message="tns:DuplicateTraitsFaultMessage"/> <wsdl:fault name="unknownTraitsException"

message="tns:UnknownTraitsFaultMessage"/> <wsdl:fault name="invalidWeightException"

message="tns:InvalidWeightFaultMessage"/> </wsdl:operation> </wsdl:portType> <!-- … -->

Page 101: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

79

79

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Finalizada la parte abstracta del documento WSDL, comienza la parte concreta con los elementos <binding>,

que describen cómo deben invocarse las operaciones han sido definidas en los elementos <portType>. El

atributo type del binding hace referencia al portType. El elemento <soap:binding> indica que se usará un

binding de SOAP 1.1, la URI asignada al atributo transport identifica a HTTP como el protocolo de transporte

(SOAP sobre HTTP) a usar, y el atributo style establece document como el estilo para los mensajes SOAP. Por

cada operación se especifica el tipo de codificación (use) que se usará en el cuerpo de los mensajes de entrada,

salida y fault. La operación será para todos los casos Document/literal. No se ha especificado ninguna URI para

el atributo soapAction, que representa la cabecera SOAPAction HTTP enviada con cada petición para poder

filtrar los mensajes SOAP.

PID.wsdl -- Binding: IdentifyPerson

<!-- … --> <wsdl:binding name="IdentifyPersonBinding"

type="tns:IdentifyPersonPortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http"

style="document"/> <wsdl:operation name="findCandidates"> <soap:operation style="document" soapAction=""/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> <wsdl:fault name="duplicateTraitsException"> <soap:fault name="duplicateTraitsException" use="literal"/> </wsdl:fault> <wsdl:fault name="unknownTraitsException"> <soap:fault name="unknownTraitsException" use="literal"/> </wsdl:fault> <wsdl:fault name="invalidWeightException"> <soap:fault name="invalidWeightException" use="literal"/> </wsdl:fault> </wsdl:operation> </wsdl:binding> <!-- … -->

Por último, los elementos <service> indican dónde se pueden invocar las operaciones del servicio Web.

Contienen elementos <port> que asocian el servicio (endpoint) a una dirección física particular. Dado que se

trata de un servicio Web SOAP, el elemento <port> alberga un elemento <soap:address> cuyo atributo

location especifica la dirección URL del servicio.

PID.wsdl -- Service: IdentifyPerson

<!-- … --> <wsdl:service name="IdentifyPersonService"> <wsdl:port name="IdentifyPersonPort" binding="tns:IdentifyPersonBinding"> <soap:address

location="http://localhost:8080/pid/services/identifyperson"/> </wsdl:port> </wsdl:service> <!-- … -->

Page 102: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

80

4.2.2 Implementación del servicio Web

La API de JAX-WS abstrae al desarrollador del procesamiento de los mensajes SOAP, la invocación de los

métodos que implementan el servicio, y la construcción del mensaje SOAP de respuesta que se devuelve al

cliente. Para facilitar aún más la tarea, JAX-WS proporciona la herramienta wsimport que, tomando como

entrada el documento WSDL que describe el servicio PIDS, genera las clases JavaBeans que mapean con los

tipos de datos definidos en los esquemas XML, así como la interfaz Java correspondiente al SEI del servicio

Web, entre otros.

En el proyecto la herramienta se utiliza invocando la tarea Ant com.sun.tools.ws.ant.WsImport. Es requisito, por

tanto, tener instalado en el entorno de desarrollo una distribución binaria de Ant. En la lista que sigue se enumeran

otros requisitos y dependencias que se han tenido en cuenta para la definición de la tarea Ant adecuada:

• La versión JDK usada no integra la clase de la tarea Ant, únicamente la herramienta de línea de

comandos. Es necesario descargar las librerías de Metro (apartado 3.4) e incluirlas en el classpath.

Concretamente la tarea Ant está disponible en el paquete webservices-tools.jar.

• MyBatis se apoya en los métodos getters y setters de las propiedades de los JavaBeans que se pasan en

los métodos de las sentencias para mapearlos con los parámetros de consulta (usando Reflection). Sin

embargo, JAXB genera las clases de acuerdo con la especificación oficial de los JavaBeans que

establece que el método getter para las propiedades boolean sean del tipo boolean

is<PropertyName>(). wsimport usa el compilador xjc para la generación de las clases Java, y una

de las características más importantes de xjc es que se puede extender mediante plugins que modifiquen

o personalicen el código generado. En este sentido, se ha utilizado el plugin booleangetter.jar que

genera el método getter necesario para las propiedades de tipo primitivo boolean.

• Por defecto, xjc no crea métodos toString, útiles especialmente para pruebas con clientes simples, ni

métodos setters para las clases de tipo Collection. La extensión JAXB2 Basics Plugins [30] (jaxb2-

basics-plugins-*.jar) cubren estas características que se echan en falta.

Nota: para usar las extensiones de JAXB hay que incluir las librerías del plugin en el classpath y activarlo

añadiendo los argumentos de xjc correspondientes.

build.xml -- wsimport

<!-- … --> <taskdef name="wsimport" classname="com.sun.tools.ws.ant.WsImport"> <classpath refid="jaxws.classpath"/> <classpath> <pathelement location="${service.src.dir}/java"/> <pathelement path="${service.src.dir}/webapp/WEB-INF/lib/booleangetter.jar"/> <pathelement path="${service.src.dir}/webapp/WEB-INF/lib/jaxb2bas0.11.0.jar"/>

</classpath> </taskdef> <wsimport sourcedestdir="${target.gen.dir}" wsdl="${wsdl.location}"

xnocompile="true"> <xjcarg value="-Xboolean-getter"/> <xjcarg value="-XtoString"/> <xjcarg value="-Xsetters"/> <xjcarg value="-Xsetters-mode=direct"/> </wsimport> <!-- … -->

Los artefactos generados se organizan en paquetes tomando como referencia los targetNamespace declarados

Page 103: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

81

81

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

en el documento WSDL y los esquemas XML. Los paquetes y clases resultantes tras la invocación de wsimport

con el fichero WSDL del servicio PIDS se resumen a continuación:

• pid.pfc.service.beans: contiene los JavaBeans de los datos demográficos de referencia, tanto

tipos básicos como CAG y GPICS, correlacionados desde los tipos de uno de los esquemas XML.

• pid.pfc.xsd: paquete con las clases mapeadas del esquema XML referente a los tipos de datos de

la especificación del PIDS, y las clases correspondientes a los parámetros de entrada, excepciones y

valores devueltos utilizados en los métodos de las interfaces del PIDS.

Los paquetes generados a partir de los esquemas XML incluyen una clase ObjectFactory, con los métodos de

factoría de cada clase o interfaz generada, y otra package-info, que proporciona la declaración del paquete

asociado a partir del targetNamespace del esquema XML.

• pid.pfc.wsdl: junto con las clases para el tratamiento de los mensajes de excepción, incluye las

clases del SEI, IdentifyPersonPortType y ProfileAccessPortType, con la definición de los métodos de

las interfaces del PIDS, y las clases IndentifyPersonService y ProfileAccessService, utilizadas por el

cliente JAX-WS para comunicarse con el servicio Web a través del SEI.

Page 104: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

82

Centrándose en la interfaz IdentifyPerson, la clase IdentifyPersonPortType representa el SEI, anotada con

@WebService (javax.jws.WebService). La clase también tiene la anotación @SOAPBinding para especificar

el estilo y la codificación de los mensajes SOAP utilizados al invocar el servicio. El atributo parameterStyle con

el valor SOAPBinding.ParameterStyle.BARE determina que los parámetros del método representan

todo el cuerpo del mensaje. En este caso, la interfaz declara únicamente el método findCandidates. La anotación

@WebMethod indica que debe ser publicado como operación del servicio, mientras que las anotaciones

@WebParam y @WebResult asociadas al método determinan los nombres de los parámetros y resultados

del método en el fichero WSDL.

IdentifyPersonPortType.java

// … @WebService(name = "IdentifyPersonPortType",

targetNamespace = "http://pfc.pid/wsdl") @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface IdentifyPersonPortType { @WebMethod @WebResult(name = "findCandidatesRes",

targetNamespace = "http://pfc.pid/xsd",

partName = "result") public FindCandidatesRes findCandidates( @WebParam(name = "findCandidatesReq",

targetNamespace = "http://pfc.pid/xsd",

partName = "parameters") FindCandidatesReq parameters) throws DuplicateTraitsFaultMessage,

InvalidWeightFaultMessage,

UnknownTraitsFaultMessage ; }

La clase IdentifyPersonPortTypeImpl representa el SIB, que proporciona una implementación del SEI.

También debe estar anotada con @WebService añadiendo, como mínimo, el atributo endpointInterface para

vincular el SIB a su SEI correspondiente. Sin embargo, los métodos del SIB no tienen que estar anotados con

@WebMethod; esta anotación sólo se usa en el contexto del SEI.

Page 105: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

83

83

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Es una buena práctica activar la validación de los esquemas de los mensajes enviados al servicio Web,

especialmente para detectar cualquier problema en el formato de los mensajes entrantes. Basta con añadir la

anotación @SchemaValidation (com.sun.xml.ws.developer.SchemaValidation) a nivel de servicio Web. No

obstante, hay que tener en consideración que esta validación está deshabilitada por defecto porque tiene un

impacto significativo sobre el rendimiento.

IdentifyPersonPortTypeImpl.java

// … @SchemaValidation() @WebService(serviceName = "IdentifyPersonService", portName = "IdentifyPersonPort", endpointInterface = "pid.pfc.wsdl.IdentifyPersonPortType", targetNamespace = "http://pfc.pid/wsdl")

public class IdentifyPersonPortTypeImpl implements IdentifyPersonPortType {

// … }

4.2.3 Estructura de carpetas para el proyecto y ficheros de despliegue

Para construir el proyecto del servicio Web primero es necesario crear una estructura de carpetas adecuada que

facilite el desarrollo iterativo de versiones y mantenga el código fuente independiente de los ficheros compilados.

Está basado en las convenciones estructurales recomendadas para proyectos Maven [31]. La estructura se diseña

con el objetivo último de implementar el servicio Web utilizando el modelo de programación de servlets y, por

tanto, empaquetar el servicio en un WAR que se desplegará sobre un contenedor de servlets. Concretamente

para el proyecto, el contenedor donde se despliegue será un servidor Tomcat.

Figura 4-4. Estructura del proyecto de servicio Web

La carpeta raíz será el directorio de trabajo desde el que ejecutar los objetivos ("targets") Ant que automatizan las

tareas habituales de generación (wsimport), compilación, construcción y despliegue. El fichero build.xml alojado

Page 106: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

84

en el directorio es el que describe los objetivos con cada una de las tareas a ejecutar. Bajo la carpeta raíz del

proyecto se crean dos carpetas en los que se guardan por separado todos los recursos y código relacionado con

la parte del cliente y del servidor PIDS. Haciendo foco en la carpeta para el servicio, el contenido y la finalidad

de cada subcarpeta se describe como sigue:

src/main/java Código fuente del servicio

src/main/resources Ficheros XML mappers de MyBatis y árbol de traits, ficheros de propiedades

src/main/webapp Recursos para una aplicación Web. Contiene el directorio WEB-INF

target/classes Clases compiladas

target/generated Artefactos JAX-WS generados con wsimport a partir del WSDL y esquemas

XML

El directorio WEB-INF contiene toda la información de configuración necesaria para un servicio Web

empaquetado en un WAR. De acuerdo a este modelo de despliegue, el fichero WSDL se almacena en el

subdirectorio WEB-INF/wsdl para su publicación durante el despliegue, y la descripción del despliegue en el

servidor Tomcat (contenedor no Java EE) se define en los ficheros web.xml y sun-jaxws.xml.

• En el fichero web.xml se declara el agente de escucha ("listener") WSServletContextListener, que

inicializa y configura el port del WSDL del servicio Web, y el registro del servlet WSServlet de JAX-

WS, que entrega las peticiones al servicio, utilizando la clase que implementa dicho servicio. El fichero

web.xml no es obligatorio a partir de la API Servlet 3.0, y Metro puede crear automáticamente el registro

del servlet JAX-WS predeterminado cuando se utilizan contenedores no-Java EE.

• El fichero sun-jaxws.xml contiene la definición de la implementación de los endpoints del servicio. Cada

endpoint representa un port del WSDL, y contiene toda la información sobre la clase que implementa

el servicio, el patrón URL del servlet (debe encajar con el patrón indicado en el fichero web.xml) para

el acceso HTTP, la ubicación del fichero WSDL, y los nombres del port y service del WSDL.

Por ejemplo, en el siguiente extracto del fichero sun-jaxws.xml se indica que la implementación del

servicio viene dada por la clase pid.pfc.service.impl.IdentifyPersonPortTypeImpl (dicha clase debe

estar anotada con @WebService).

sun-jaxws.xml

<!-- … -->

<endpoint name="Endpoint_for_IdentifyPerson" implementation="pid.pfc.service.impl.IdentifyPersonPortTypeImpl" wsdl="WEB-INF/wsdl/PID.wsdl" service="{http://pfc.pid/wsdl}IdentifyPersonService" port="{http://pfc.pid/wsdl}IdentifyPersonPort" url-pattern="/services/identifyperson"/>

<!-- … -->

Nota: No es necesario especificar en el fichero de sun-jaxws.xml información del binding ni usar la anotación

@BindingType, ya que el binding por defecto es SOAP1.1/HTTP

Las librerías o ficheros JAR de los que dependa el servicio Web se ubican en el directorio WEB-INF/lib y serán

agregados automáticamente al classpath del servicio en tiempo de ejecución. El directorio contendrá, por

ejemplo, las librerías de MyBatis, el controlador JDBC de la base de datos, y los plugins de xjc. Además,

teniendo en cuenta que Tomcat no es un contenedor que cumpla las especificaciones Java EE completamente,

es preciso incluir también las librerías concretas de JAX-WS para que pueda trabajar con servicios Web.

Page 107: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

85

85

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

4.2.4 Ant (secuencia de tareas)

Con el código fuente, los ficheros de recursos y configuración, las librerías externas dependientes, y el

documento WSDL en la carpeta adecuada, se puede automatizar el proceso de empaquetamiento y distribución

del proyecto conforme a la invocación secuencial de tareas Ant sencillas contenidas en el fichero build.xml.

La secuencia de despliegue consta de un primer objetivo, generate-jaxws-classes, que procesa el fichero WSDL

para generar los artefactos JAX-WS. Se utiliza la tarea Ant de wsimport descrita anteriormente, a la que se le

especifica la ruta donde guardar el código fuente generado, la ubicación del fichero WSDL, la opción xnocompile

para que no compile el código generado, y las propiedades de personalización para el compilador xjc a partir de

los plugins JAXB. El siguiente objetivo se encarga de compilar todo el código fuente del proyecto, tanto de la

parte cliente como la parte del servidor. Una vez compilado, el objetivo create-jaxws-war empaqueta la

aplicación mediante la tarea Ant predefinida war. A partir de los elementos anidados en la tarea se agregan los

recursos necesarios (clases, ficheros XML, propiedades, librerías) al fichero WAR resultante.

<lib> Todos los ficheros incluidos en la ruta del atributo dir, a excepción de los

explícitamente excluidos, se guardarán en el directorio WEB-INF/lib del WAR

<classes> Todos los ficheros incluidos en la ruta del atributo dir, a excepción de los

explícitamente excluidos, se guardarán en el directorio WEB-INF/clases del

WAR

<webinf> Todos los ficheros incluidos en la ruta del atributo dir, se guardarán en el

directorio WEB-INF del WAR Se utiliza para añadir el fichero sun-jaxws.xml. Nota: el descriptor web.xml a utilizar se indica mediante el atributo obligatorio

webxml de la tarea war.

<zipfileset> Clases compiladas

Por lo general, el WAR del servicio Web contiene el fichero WSDL, la clase SEI, la clase que implementa el

servicio y sus clases dependientes, los artefactos JAX-WS generados, las librerías dependientes del servicio, y

los descriptores de despliegue.

Finalmente, se puede desplegar el WAR en el contenedor Tomcat. El objetivo Ant deploy-war espera que le

ingresen una ruta local válida donde realizar la copia del WAR.

Con el Tomcat iniciado, para verificar que el servicio Web está ejecutándose correctamente simplemente habría

que introducir, por ejemplo, la dirección http://localhost:8080/pid/services/identifyperson en cualquier

navegador Web y se obtiene una página con la descripción de los metadatos de los endpoints junto con la URI

del WSDL (coincide con la URI del servicio Web con el sufijo ?wsdl) y el nombre cualificado de las clases

que implementa los SEI.

Figura 4-5. publicación servicio Web

Page 108: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

86

Nota: si se accede a cualquiera de los dos endpoints, JAX-WS enumera todos los endpoints definidos en la

aplicación. Igualmente, si se consulta el fichero WSDL de cualquier de los endpoints, se devuelve el mismo

archivo XML (los endpoints se han definido a partir del mismo archivo).

Esta información es la que usa un cliente para acceder y consumir el servicio.

4.2.5 Cliente del servicio Web

La herramienta wsimport, a partir del WSDL del servicio Web, facilita la creación de clientes JAX-WS sencillos

no gestionados (no ejecutados en contenedor Java EE) siguiendo el modelo de programación de cliente proxy

dinámico. Genera la clase que extiende la clase javax.xml.ws.Service cuyos métodos instancian al SEI para

habilitar un proxy de comunicación con el servicio Web. Desde esta forma, los clientes acceden a la

implementación del servicio Web mediante llamadas directas sobre los métodos del SEI, ajenos a si el servicio

está ejecutando en local o remoto, y siendo transparente para ellos todo lo relacionado con el transporte o la

codificación de los mensajes.

Suponiendo el caso práctico de un cliente que quiera ejecutar la operación findCandidates de la interfaz

identifyPerson, primero hay que importar al cliente los artefactos JAX-WS generados por wsimport. Si se desea

aprovechar las características de extensión del compilador de JAXB xjc, la manera más sencilla de invocar

wsimport es ejecutar una tarea Ant com.sun.tools.ws.ant.WsImport, similar a lo visto en un punto anterior de este

capítulo. En este caso, la opción relativa a la localización del WSDL apuntará a la URI de algunos de los

endpoints del servicio Web. Por ejemplo, http://localhost:8080/pid/services/identifyperson?wsdl.

Luego, tanto solo habrá que instanciar la clase identifyPersonService e invocar el método getIdentifyPersonPort

que devuelve una instancia del SEI del servicio Web (identifyPersonPortType). El cliente ejecuta las

operaciones utilizando esta instancia; en este ejemplo, findCandidates.

Principal.java

// … pid.pfc.wsdl.IdentifyPersonService service = new pid.pfc.wsdl.IdentifyPersonService(); pid.pfc.wsdl.IdentifyPersonPortType port = service.getIdentifyPersonPort(); pid.pfc.xsd.FindCandidatesReq parameters = new pid.pfc.xsd.FindCandidatesReq(); // … pid.pfc.xsd.FindCandidatesRes result = port.findCandidates(parameters);

// …

El IDE Netbeans también proporciona un asistente que recrea los pasos realizados para crear un cliente de un

servicio Web de forma gráfica e interactiva. Sobre un proyecto nuevo o existente creamos un nuevo archivo de

tipo Web Service Client.

Page 109: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

87

87

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Figura 4-6. Cliente NetBeans (1)

El asistente de creación solicita la localización del fichero WSDL del servicio Web y el nombre del paquete

donde se generaran los artefactos Java para el cliente. Por ejemplo, es posible indicar la URL en la que está

publicado el WSDL. Si no se especifica ningún nombre para el paquete de destino, por defecto la estructura de

paquetes se basará en el namespace del propio WSDL. También da la opción de generar el código de un cliente

Dispatch si se desea trabajar a más bajo nivel en la construcción de los mensajes o cargas de trabajo XML.

Figura 4-7. Cliente NetBeans (2)

Finalizados los pasos de creación, NetBeans invocará a wsimport para generar los artefactos del servicio, que se

podrán listar en la carpeta Generate Sources (jaxws-wsimport) del proyecto. En otra carpeta del proyecto, Web

Service References, se obtiene una referencia a los endpoints y operaciones disponibles en el servicio Web.

Page 110: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

88

Figura 4-8. Cliente NetBeans (3)

NetBeans también proporciona un atajo para crear el código que invoca al servicio. Basta con arrastrar la

operación deseada desde la carpeta Web Service References a la parte en la que se quiera insertar el código de la

clase que se estuviera editando. Otra opción sería desde el menú de NetBeans Source > Insert Code … > Call

Web Service Operation.

Figura 4-9. Cliente NetBeans (4)

Sólo estaría pendiente la edición el código para especificar los parámetros de entrada necesarios para la

operación.

Este mismo proceso se aplica para insertar el código de invocación en los métodos de acción de la interfaz

gráfica del cliente diseñado con la librería Swing.

Figura 4-10. Cliente GUI

Page 111: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

89

89

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

4.3 Fase 3: Despliegue en contenedores

En el arranque de esta fase del proyecto, el servidor PIDS parte de una arquitectura en la que todos sus

componentes técnicos están ejecutándose localmente sobre la misma máquina, sin posibilidad de proporcionar

una plataforma escalable y que garantice la alta disponibilidad del servicio. De cara a facilitar la gestión del ciclo

de vida de la aplicación hasta su puesta en producción, es necesario adecuar un entorno de desarrollo que permita

agilizar la puesta en marcha de diferentes escenarios para la realización de pruebas, que reduzca la dependencia

con la configuración del propio entorno, y que posibilite mantener un control de versiones de cada componente

para su posible restauración.

Se ha visto que los contenedores están cosechando una rápida aceptación como mecanismo de entrega para

aplicaciones, en gran parte debido a que permite la provisión de entornos uniformes para implementar

aplicaciones, con independencia del sistema operativo, la distribución o infraestructura en la que se ejecute. Así

se resuelven muchos de los problemas habituales en la puesta en producción relacionados con dependencias o

inconsistencias entre los entornos de desarrollo y producción.

A lo largo del apartado se va a describir el proceso de despliegue del servicio PIDS en un entorno basado en

contenedores Docker. Al tratarse de una aplicación sin estado ("stateless"), al menos a nivel de servicio Web,

encaja muy bien con la filosofía de contenedores. Además, gracias a la versatilidad que proporciona el

ecosistema de herramientas de Docker, es posible optar por diferentes modalidades de despliegue para simular,

por ejemplo, diferentes contextos de demanda del servicio. Se plantearán dos escenarios, uno de baja demanda

o con fines de desarrollo en el que los contendores que dan soporte al servicio se despliegan sobre una única

máquina, y otro de alta demanda que exige, entre otras características, dotar al servicio de prestaciones

productivas relacionadas con la tolerancia a fallos o la capacidad de escalado "al vuelo". En este segundo caso

el servicio PIDS estará apoyado en una arquitectura de clúster multinodo, implementada sobre un entorno de

instancias Cloud.

Para todos los escenarios establecidos en el proyecto, cada uno de los servicios técnicos que componen

el stack tecnológico del PIDS se empaquetará en contenedores de servicios específicos y autónomos que

interactuarán entre sí. Rápidamente se puede diferenciar una capa de servicio Web y otra de base de datos para

dar soporte funcional al PIDS, que se pueden separar en contenedores para gestionarlos (desplegarlos,

actualizarlos, escalarlos, etc.) individualmente. Así, la arquitectura de base estará formada por contenedores que

ejecutan, por una parte, un servidor Tomcat donde alojar el WAR con el servicio Web del PIDS, y, por otro lado,

una base de datos PostgreSQL inicializada mediante un fichero .sql que contiene las sentencias de creación de

la estructura del PIDS y valores iniciales de cada tupla.

El apartado se va a organizar empezando con una breve descripción de las imágenes Docker que se usarán en la

ejecución de los contenedores necesarios, y continuar con la exposición detallada del proceso de despliegue de

los contenedores en los escenarios antes comentados. Dado que con Docker prácticamente todo puede ser

definido en ficheros de configuración, el objetivo último será la conseguir el máximo nivel de automatización

del despliegue y administración de los contenedores de servicios.

Es un prerrequisito para el seguimiento del apartado tener instalado Docker, Docker Compose y Docker

Machine.

4.3.1 Descripción de las imágenes Docker

Con carácter práctico, la imagen de un contenedor se trata fundamentalmente del sistema de archivos preparado

que usará el proceso que se ejecuta en el contenedor, tal y como se explicó en el apartado 3.6.2.1. En Docker

Hub (apartado 3.6.2.2) se pueden encontrar las imágenes oficiales de los dos componentes requeridos: Tomcat

y PostgreSQL. No obstante, se crearán ficheros Dockerfile por cada componente para extender mínimamente

las imágenes oficiales y adaptarlas a las necesidades particulares del proyecto. Se recuerda que un fichero

Dockerfile es una especie de manifiesto donde especificar las características de la imagen, el software adicional

que debe tener instalado, librerías, servicios y configuraciones.

Para tener un mejor control de versiones, se crea una estructura de carpetas en la que mantener los ficheros de

Dockerfile de cada componente:

Page 112: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

90

Figura 4-11. Estructura proyecto Docker

Dentro la carpeta data de cada componente se añaden todos los recursos y ficheros que serán necesarios adjuntar

a la imagen para la inicialización de los contenedores correspondientes.

4.3.1.1 Imagen db

Se corresponde con la base de datos del proyecto. En su carpeta data se guarda un fichero .sql equivalente a un

dump de la base de datos que incluye las sentencias SQL de creación de las tablas y la inserción de datos iniciales

de prueba, y un script de inicialización para la creación la base de datos del proyecto y un nuevo rol. El script

también se encarga de ejecutar el dump anterior para crear la estructura de la base de datos y cargar los datos de

prueba.

El contenido del Dockerfile es el siguiente:

Dockerfile -- db

FROM postgres:9.5 COPY ./data/init.sh /docker-entrypoint-initdb.d/1-init-dbpid.sh COPY ./data/backup-PID.sql /sql/init.sql

La nueva imagen toma como base la imagen estándar de PostgreSQL [32]. La etiqueta ("tag") 9.5 especifica la

versión del software que se va a usar.

Según la documentación de la imagen de PostgreSQL, en caso de tener que realizar tareas de inicialización

adicionales, la imagen está preparada para ejecutar cualquier fichero .sql o script .sh que se localice en el

directorio /docker-entrypoint-initdb.d del contenedor en el momento de su creación. La primera instrucción

COPY hace la copia del del script de inicialización en el directorio indicado del contenedor. El propio script va

a ejecutar el fichero .sql, por lo que no hay necesidad expresa de añadirlo en el mismo directorio. Si hubiera

varios ficheros de inicialización, se ejecutarían en orden alfabético, por eso es una buena práctica prefijarlos con

una numeración que establezca el orden en que se deben ejecutar. De forma predeterminada, la imagen de

PostgreSQL tiene configurada autenticación trust desde el acceso local, lo que significa que no será necesario

proporcionar una contraseña en estos scripts que se ejecutan desde el propio contenedor.

Hay varias variables de entorno opcionales definidas en la imagen que pueden ayudar en la inicialización del

contenedor. Algunas de las variables que se usarán habitualmente son:

• POSTGRES_PASSWORD: establece la contraseña del superusuario de PostgreSQL.

• POSTGRES_USER: creará el rol especificado con permisos de superusuario y una base de datos con el

mismo nombre. Si no se especifica, se usará el usuario predeterminado postgres.

• POSTGRES_DB: define un nombre diferente para la base de datos predeterminada creada al iniciar por

primera vez la imagen. Si no se especifica, se usará el valor de la variable POSTGRES_USER.

Adicionalmente, el script de inicialización se ha desarrollado para utilizar otras variables de entorno que deben

proporcionarse en el despliegue del contenedor:

• PID_PASS: variable requerida. Establece la contraseña para el rol PID_USER.

Page 113: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

91

91

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

• PID_DB: nombre de la base de datos usada para el proyecto. Si no se especifica, se le asigna el valor

"PID" por defecto.

• PID_USER: nombre del rol propietario de la base de datos PID_DB. Si no se especifica, el valor por

defecto es "ibatis".

Además, los ficheros .sql que se encuentren en el directorio /docker-entrypoint-initdb.d se ejecutarán con el

usuario especificado en la variable POSTGRES_USER.

Situándose en la carpeta del proyecto (docker_project), para construir la imagen se usa el comando docker build

de la siguiente forma:

$ docker build -t dockg6/pid:db.10 db/.

Sending build context to Docker daemon 98.3kB

Step 1/3 : FROM postgres:9.5

---> 988f714a7307

Step 2/3 : COPY ./data/init.sh /docker-entrypoint-initdb.d/1-init-dbpid.sh

---> b56aba186fa5

Step 3/3 : COPY ./data/backup-PID.sql /sql/init.sql

---> 083b131f471e

Successfully built 083b131f471e

Successfully tagged dockg6/pid:db.10

Nota: ya estaba descargada la imagen de postgres:9.5. Por eso en la salida del comando anterior no aparece

la descarga de las 12 capas que forman la imagen.

La opción -t permite nombrar y etiquetar la imagen con el formato "nombre:etiqueta". El comando

buscará un fichero de nombre Dockerfile en la ruta especificada.

4.3.1.2 Imagen webApp

Para desplegar el WAR del servicio Web generado en la fase anterior del proyecto es necesario disponer de un

contenedor que ejecute el servidor Apache Tomcat. Su carpeta data debe coincidir con la ruta especificada en el

objetivo Ant deploy-war del proceso de distribución del servicio Web.

El contenido del Dockerfile es el siguiente:

Dockerfile -- webApp

FROM tomcat RUN rm -rf /usr/local/tomcat/webapps/* COPY ./data/pid.war /usr/local/tomcat/webapps/pid.war

La nueva imagen toma como base la imagen estándar de Tomcat [33]. Al no haber especificado tag de la imagen,

automáticamente usará la versión latest si existiese.

Nota: no se recomienda usar las versiones latest para el despliegue de contenedores en entornos productivos

ya que podría estar aplicando modificaciones en la arquitectura que afecten a la estabilidad del servicio sin

haber hecho pruebas previamente. Por ejemplo, si se volviera a construir la imagen pasado un tiempo, la capa

principal podría haberse actualizado y ser incompatible con versiones anteriores.

Page 114: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

92

A continuación, se ejecuta el comando rm para borrar las aplicaciones Web que vienen por defecto con la imagen

oficial, y finalmente copia el fichero WAR del servicio Web en el directorio webapps, desde donde Tomcat se

encargará de desplegarlo automáticamente en el inicio del contenedor.

Ya solo falta construir la imagen con el comando docker build:

$ docker build -t dockg6/pid:webApp.10 webApp/.

Sending build context to Docker daemon 18.64MB

Step 1/3 : FROM tomcat

---> 11df4b40749f

Step 2/3 : RUN rm -rf /usr/local/tomcat/webapps/*

---> Running in ebd088c59e71

---> 2bda9ecd0c6d

Removing intermediate container ebd088c59e71

Step 3/3 : COPY ./data/pid.war /usr/local/tomcat/webapps/pid.war

---> 36ebb39a905f

Successfully built 36ebb39a905f

Successfully tagged dockg6/pid:webApp.10

4.3.2 Despliegue local

Una vez construidas las imágenes para el proyecto, ya se podrían iniciar contenedores relativos a las imágenes

con el comando docker run. Sin embargo, el despliegue standalone, por separado, de contenedores que

pertenecen a una misma aplicación dificulta la administración y orquestación de los contenedores para iniciarlos,

detenerlos e interconectarlos de forma ordenada. Siempre existe la posibilidad de crear una capa de networking

entre ellos, pero de forma descentralizada. Dentro del ecosistema de Docker hay herramientas disponibles para

facilitar la administración de contenedores que están relacionados entre sí. En este apartado se utilizará Docker

Compose (apartado 3.6.3.1), una herramienta para orquestar contenedores Docker iniciados sobre una misma

máquina, cuyo archivo YAML, donde se describe la configuración del stack de la aplicación multi-contenedor,

se utilizará como base para el despliegue de los contenedores en un clúster de nodos distribuidos.

Hay que añadir el fichero .yml descriptor de los contenedores en la raíz de la estructura de carpetas del proyecto

para usar Docker Compose.

Figura 4-12. Estructura proyecto Docker - Compose

El fichero pid-compose.yml se puede descomponer en tres bloques: services, donde se declaran los dos

contenedores, db y webApp, que componen la aplicación y cual va a ser la configuración de los contenedores,

networks, con la configuración de las redes que se van a usar, y volumes, en la que se especifican los volúmenes

de datos persistentes provistos para la aplicación.

Page 115: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

93

93

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

pid-compose.yml

version: '3.4' services: db: container_name: pid-db build: ./db image: dockg6/pid:db.10 ports: - "5432:5432" volumes: - dbdata:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=changeit - PID_DB=PID - PID_USER=ibatis - PID_PASS=changeitPID networks: - pid-network webApp: container_name: pid-webApp build: ./webApp image: dockg6/pid:webapp.10 depends_on: - db ports: - "8080:8080" networks: - pid-network networks: pid-network: volumes: dbdata:

Al generar los contenedores, este fichero le especifica a Docker que haga lo siguiente:

• Crea la red llamada <project-name>_pid-network con los parámetros de red por defecto. Al no haber

especificado ningún driver concreto, será de tipo bridge. Si tampoco se hubiera especificado ninguna

red, por defecto se crea una a partir del nombre del proyecto; en este caso, docker_project.

• Crea el volumen de datos local, en el sistema de ficheros del anfitrión, nombrado <project-

name>_dbdata.

• Los contenedores que se generen deben tener los nombres indicados en la propiedad container_name.

• Construye las imágenes correspondientes a cada contenedor en base a la ubicación de los ficheros

Dockerfile indicada con la opción build. Al haber especificado también la instrucción image, se

nombrarán de acuerdo al nombre y etiqueta indicada.

• Mapea mediante ports el puerto 8080 del contenedor Tomcat al puerto 8080 del sistema anfitrión, y

aunque no es estrictamente necesario para el funcionamiento de la aplicación, también se publica el

puerto 5432 de PostgreSQL por comodidad, para poder desempeñar tareas de administración sobre la

base de datos desde la máquina anfitriona, en lugar de tener que realizarlas desde otros contenedores

temporales conectados a la misma red.

Page 116: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

94

• Vincula el volumen anterior a la ruta donde PostgreSQL almacena toda configuración y datos de la base

de datos para ganar persistencia más allá del ciclo de vida del contenedor db.

• Proporciona los valores de las variables de entorno declaradas en la opción environment, que se utilizan

para inicializar el contenedor de base de datos.

• Establece una dependencia entre los contenedores. Con la opción depends_on el contenedor db se inicia

siempre antes del webApp, y la ejecución del contenedor webApp conlleva implícitamente el inicio del

contenedor db.

• Agrega ambos contenedores a la red pid-network para que puedan intercomunicarse.

La primera línea indica la versión del formato del fichero compose que se está usando e indica las opciones

soportadas en el fichero. La sintaxis de los ficheros compose se ha ido modificando para mantener la

compatibilidad con nuevas funcionalidades introducidas en las revisiones de Docker (enlace). La versión más

reciente y recomendada en la 3.X, diseñada especialmente para asegurar la compatibilidad cruzada entre Docker

Compose y Docker en modo Swarm.

Una característica interesante, de entre otras opciones que no se han configurado, es la posibilidad de establecer

restricciones para controlar la asignación de recursos, en términos de CPU y memoria, que pueden consumir

cada contenedor. De esta forma, se evita que un contenedor pueda agotar todos los recursos, limitando el impacto

sobre otros contenedores e incluso sobre el propio sistema host. Del mismo modo, se podrían reservar unos

recursos mínimos para los contenedores.

Para ejecutar la aplicación se utiliza el siguiente comando desde el directorio raíz del proyecto, en que también

está el fichero compose.

$ docker-compose -f pid-compose.yml -p pid up -d/.

Creating network "pid_pid-network" with the default driver

Creating volume "pid_dbdata" with default driver

Building db

Step 1/3 : FROM postgres:9.5

---> 988f714a7307

Step 2/3 : COPY ./data/init.sh /docker-entrypoint-initdb.d/1-init-dbpid.sh

---> 9dd1a62bc8ea

Step 3/3 : COPY ./data/backup-PID.sql /sql/init.sql

---> 8f52b031aeb8

Successfully built 8f52b031aeb8

Successfully tagged dockg6/pid:db.10

WARNING: Image for service db was built because it did not already exist. To

rebuild this image you must use

`docker-compose build` or `docker-compose up --build`.

Building webApp

Step 1/3 : FROM tomcat

---> 11df4b40749f

Step 2/3 : RUN rm -rf /usr/local/tomcat/webapps/*

---> Running in d44f9c64c37b

---> c2fd45a27680

Removing intermediate container d44f9c64c37b

Step 3/3 : COPY ./data/pid.war /usr/local/tomcat/webapps/pid.war

---> b9e55db67ca0

Successfully built b9e55db67ca0

Successfully tagged dockg6/pid:webapp.10

WARNING: Image for service webApp was built because it did not already exist. To

rebuild this image you must use

`docker-compose build` or `docker-compose up --build`.

Creating pid-db ...

Creating pid-db ... done

Creating pid-webApp ...

Creating pid-webApp ... done

Page 117: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

95

95

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Al no haber usado el nombre por defecto para el fichero compose (docker-compose.yml), con la opción -f se

especifica el nombre del fichero alternativo. La opción -d configura la ejecución de los contenedores en segundo

plano.

Nota: es importante haber cambiado la ruta de conexión a la base de datos configurada para MyBatis para que

contenga el nombre del contendor de PostgreSQL. En este caso la ruta sería jdbc:postgresql://pid-db:5432/PID

Figura 4-13. Esquema de contenedores en despliegue local

Parar y eliminar los contenedores, redes y volúmenes que componen la aplicación se hace mediante el siguiente

comando:

$ docker-compose -f pid-compose.yml -p pid down -v

Stopping pid-webApp ... done

Stopping pid-db ... done

Removing pid-webApp ... done

Removing pid-db ... done

Removing network pid_pid-network

Removing volume pid_dbdata

Volviendo al fichero compose, ha sido necesario especificar "en claro" las contraseñas de los usuarios de

PostgreSQL, no siendo esta circunstancia deseable a efectos de seguridad. Además, estos datos se proporcionan

mediante variables de entorno, por lo que al hacer un listar los procesos junto con sus parámetros de invocación

quedarán expuestos. Docker Compose también soporta la declaración de múltiples variables de entorno en un

fichero .env externo sobre el que se podría establecer un control de acceso más estricto.

pid-compose.yml -- environment file

… db: … env-file: - ./db/data/postgres-var.env … …

Page 118: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

96

postgres-var.env

POSTGRES_PASSWORD=changeit PID_DB=PID PID_USER=ibatis PID_PASS=changeitPID

No obstante, los datos sensibles seguirán expuestos a cualquiera mal uso de las variables de entorno.

$ docker inspect -f "{{json .Config.Env}}" pid-db | \

sed 's/"//g;s/\[//g;s/\]//g' | \

tr ',' '\n'

POSTGRES_PASSWORD=changeit

PID_USER=ibatis

PID_DB=PID

PID_PASS=changeitPID

LANG=en_US.utf8

PG_MAJOR=9.5

PG_VERSION=9.5.10-1.pgdg80+1

PGDATA=/var/lib/postgresql/data

La mejor forma de tratar estos datos sensibles es mediante la administración centralizada de secretos que

implementa Docker (apartado 3.6.4.4). Se recuerda que, utilizando una conexión TLS, un secreto se transmite

de manera segura sobre la red, y cuando se vincula a un servicio, sólo los contenedores de ese servicio tienen

acceso a él. Además, la información sensible nunca se escribe en disco, sino que el secreto es almacenado en un

volumen temporal (tmpfs) que se monta en memoria bajo la ruta /run/secrets/<nombre_secreto>.

Sin embargo, Docker Secrets es una función nativa de Docker en modo Swarm (apartado 3.6.4), por lo que

habría que adaptar los contenedores actuales para que se ejecuten como "servicios". Los nodos managers del

swarm se encargan de coordinar la administración de secretos, cifrados en el log Raft que comparten.

A fin de mantener el mismo esquema que se venía describiendo con Docker Compose y utilizando la

terminología de Docker en modo Swarm, el stack de servicios se ejecutará en un único nodo, a escala de una

tarea por servicio. Aunque se puede tomar como referencia el mismo fichero compose que se estaba utilizando,

hay que aplicar algunos cambios menores sobre el fichero para describir el stack y la forma de desplegarlo, así

como incluir la definición de los secretos.

pid-compose_secrets.yml

version: '3.4' services: db: image: dockg6/pid:db.20 volumes: - dbdata:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD_FILE=/run/secrets/postgres-pass - PID_DB=PID - PID_USER=ibatis - PID_PASS_FILE=/run/secrets/pid-pass networks:

Page 119: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

97

97

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

- pid-network secrets: - pid-pass - postgres-pass webApp: image: dockg6/pid:webapp.20 ports: - "8080:8080" depends_on: - db networks: - pid-network secrets: - source: pid-file

target: pidfile.properties

networks: pid-network:

volumes: dbdata:

secrets: pid-pass: external: true pid-file:

file: ./webApp/data/secrets/pidfile.properties

postgres-pass: external: true

Las modificaciones realizadas con respecto al fichero compose anterior son:

• Se omite la opción container_name en la definición de los servicios.

• La opción build es ignorada cuando se despliega un stack en modo Swarm. Sólo se admiten imágenes

pre-construidas.

• Se declaran los secretos postgres-pass, pid-pass y pid-file utilizados por los servicios del stack en el

nuevo bloque secrets. Los secretos pid-pass y postgres-pass son declarados como external, lo que

significa que se tratan de referencias a secretos ya creados en el swarm, mientras que pid-file se crea en

el momento del despliegue del stack a partir del contenido del fichero referenciado en el compose. El

servicio db usa los secretos pid-pass y postgres-pass, y webApp sólo pid-file.

• Las variables de entorno asociadas a las contraseñas obtienen sus valores de los respectivos secretos

localizados en la carpeta /run/secrets del contenedor. La imagen de PostgreSQL tiene algunas variables

de entorno con variantes compatibles con secretos. Concretamente, la variable

POSTGRES_PASSWORD_FILE de la imagen está preparada para leer de un fichero.

Inicialmente el script de inicialización utilizado en la imagen de las tareas del servicio db sólo podía obtener los

valores de las variables de entorno si se le pasaban directamente. Al ampliar la funcionalidad con los secretos de

Docker, el script se modifica de forma que las variables PID_XXX también cuenten con una variante que pueda

leer sus valores a partir del contenido de los ficheros especificados en la variable PID_XXX_FILE. Una vez

actualizado, esta adaptación obliga a tener que construir una nueva versión de la imagen.

El secreto pid-file hace referencia al fichero de propiedades pidfile.properties en el que se han volcado los valores

de los parámetros de conexión a la base de datos de MyBatis que antes estaban en fichero de inicialización

ResourceData.properties. Para el correcto funcionamiento de la aplicación, los parámetros registrados en el

documento, como el usuario, contraseña o nombre de la base de datos, deben coincidir con los valores de las

variables del servicio db.

Page 120: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

98

Nota: el fichero pidfile.properties se copiará en la ruta /run/secrets del contenedor. Ha sido modificar el fichero

de configuración de MyBatis (SqlMapConfig.xml) para que pueda localizar este nuevo recurso de propiedades

fuera del classpath de la aplicación con una ruta absoluta (/run/secrets/pidfile.properties).

Para iniciar el modo Swarm se ejecuta el comando docker swarm init. Esto convertirá automáticamente la

máquina en el nodo maestro o Manager del swarm, al que se podrían ir agregando nuevos nodos. Se comprueba

también la creación por defecto de la red overlay o superpuesta ingress y la red para puentear redes overlay con

la interfaz física local docker_gwbridge (de ámbito local). Ahora, el driver de red que se utiliza por defecto es

de tipo overlay (apartado 3.6.4.3).

$ docker network ls

NETWORK ID NAME DRIVER SCOPE

103916a… bridge bridge local

ba5c4c8… docker_gwbridge bridge local

b9df448… host host local

p001q9a… ingress overlay swarm

3d0080c… none null local

Con el swarm arrancado, ya es posible ejecutar los comandos para la gestión de los secretos. Así, aquellos que

fueron declarados como recursos externos, deben estar creados previo al despliegue del stack, o de lo contrario,

el despliegue finalizará con un error de "secret not found". En el caso de postgres-pass, relativo a la contraseña

del superusuario de PostgreSQL, no necesario para el proyecto y que sólo se inicializa por motivos de seguridad,

el secreto guarda una contraseña alfanumérica aleatoria creada con el siguiente comando:

$ openssl rand -base64 30 | docker secret create postgress-pass -

Ejecutando el comando docker secret ls en el único nodo se obtiene el listado de secretos declarados en el swarm,

junto con un identificador unívoco y otras propiedades como la fecha de creación o actualización. Para obtener

más información de cada secreto se puede usar el comando docker secret inspect <secret_name>.

$ docker secret ls

ID NAME CREATED UPDATED

4tuvtfte6g41x6y… pid_postgres-pass 3 hours ago 3 hours ago

o1b2473mt6bb766… pid_pid-file 3 hours ago 3 hours ago

w1cgzda6rcn88rw… pid_pid-pass 3 hours ago 3 hours ago

Hay que tener en cuenta que es posible asignar el acceso de un servicio sobre un secreto en cualquier momento,

pero no se puede eliminar un secreto que este usando por algún servicio. Además, es importante reseñar que los

secretos son inmutables y tampoco se pueden actualizar directamente ni cambiar de nombre. Por ejemplo, en el

caso de que un secreto hubiese sido comprometido, el proceso para actualizarlo con la mínima disrupción sería

actualizar el servicio que lo use para revocar su acceso a dicho secreto y otorgarle de nuevo acceso usando el

mismo nombre del fichero destino.

Page 121: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

99

99

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

$ docker service update --secret-rm pid-pass --secret-add \

source=new-pass-pid, target=pid-pass <servicio>

Finalmente, para desplegar el stack usaremos el siguiente comando:

$ docker stack deploy -c pid-compose_secrets.yml pid

Creating network pid_pid-network

Creating service pid_db

Creating service pid_webApp

El último argumento del comando es un nombre para el stack. Cada red, volumen y nombre de servicio se

prefijan con dicho nombre.

Nota: al igual que ocurría con docker-compose, habría que volver a actualizar la URL de conexión a la base

de datos en el fichero ResourceData.properties. siguiendo el patrón

jdbc:postgresql://<stack_name>_<service_name>:5432/<dataBase_name>.

En este caso, sería jdbc:postgresql://pid_db:5432/PID

Examinando el stack se puede comprobar el estado de los dos servicios que lo componen, las tareas que soportan

los servicios, los nodos que componen el swarm, etc.

$ docker stack ls

NAME SERVICES

pid 2

$ docker stack services pid

ID NAME MODE REPLICAS IMAGE PORTS

ktr4yv4… pid_db replicated 1/1 dockg6/pid:db.20

p8vnp2u… pid_webApp replicated 1/1 dockg6/pid:webApp.20 *:8080->8080

$ docker stack ps pid

ID NAME IMAGE NODE DESIRED STATE

Icapmwds… pid_webApp.1 dockg6/pid:webApp.20 PFC Running

o2b0brr5… pid_db.1 dockg6/pid:db.20 PFC Running

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS

i0qkttr6iy61da… * PFC Ready Active Leader

En el siguiente apartado se aprovechará todo el trabajo realizado hasta el momento para desplegar el servidor

PIDS en un clúster multi-nodo Docker orquestado. Igualmente se podrá comprobar cómo al estar todo

prácticamente gestionado mediante ficheros de configuración se facilita el trabajo de cara a la programación y

automatización de todo el proceso, y por tanto al mantenimiento del proyecto bajo un sistema de control de

versiones.

Page 122: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

100

Pero antes de entrar a describir el siguiente escenario se explicará cual ha sido la medida adoptada para resolver

una de las consideraciones al usar Docker en modo Swarm: la distribución de imágenes. En el aparatado anterior

ya se comentó que un stack de Docker sólo acepta imágenes "pre-compiladas", y considerando que se va a

configurar un swarm compuesto de nodos distribuidos, es indispensable disponer un Registro como repositorio

de imágenes accesible desde los nodos swarm. De otra forma, habría que distribuir las imágenes manualmente

en cada nodo del clúster, lo cual sería impracticable. En este caso se ha usado Docker Hub, aunque igualmente

se podría haber configurado un registro privado como otro servicio más del stack.

El registro en Docker Hub da acceso a la creación de un único repositorio privado gratuito. En él se van a guardar

las imágenes personalizadas creadas para el proyecto. Con el propósito de mantener ordenados los repositorios,

el nombre de la cuenta empleada en el registro determinará el namespace bajo el que se organizan todos los

repositorios pertenecientes a una misma suscripción. Los datos de la cuenta de Docker Hub para el proyecto

serán dockg6 como namespace y pid como nombre del repositorio.

Figura 4-14. Repositorio Docker Hub

Lo habitual es que el nombre del repositorio coincida con el de la imagen que se va a contener, sin embargo, son

dos imágenes personalizadas las que se usan en el proyecto. Aunque no es lo recomendable, teniendo en cuenta

que las imágenes que se suban no van a tener una difusión fuera de este proyecto, se etiquetarán las imágenes

con un formato que permitan diferenciarlas para poder llevar un control de versiones de cada imagen con un

único repositorio.

Nota: no se muestran las etiquetas de las imágenes descargadas (docker pull) desde Docker Hub al usar el

comando docker images. Se trata de un comportamiento conocido pero que no influye en el comportamiento

del stack (Docker usa el digest de las imágenes para identificarlas. Es posible tener dos imágenes diferentes

con el mismo nombre y etiqueta, sin embargo, el digest de cada una será diferente).

Antes de subir (docker push) una imagen al repositorio, es necesario que el nombre de la imagen tenga un patrón

específico compuesto por el nombre de la cuenta, el del repositorio y, de manera opcional, un tag o etiqueta.

Habría que renombrar las imágenes (docker tag) con el formato <cuenta>/<repositorio>:<tag>. Esta es

precisamente la nomenclatura que se ha estado usando durante todo el proyecto a la hora de construir las

imágenes (docker build -t), por lo que se podría hacer la subida sin necesidad de re-etiquetar. No obstante,

primero hay que logarse en Docker Hub mediante el comando docker login.

$ docker login

Login with your Docker ID to push and pull images from Docker Hub. If you

don't have a Docker ID, head over to https://hub.docker.com to create one.

Username: dockg6

Password:

Login Succeeded

Page 123: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

101

101

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

$ docker push dockg6/pid:db.20

The push refers to a repository [docker.io/dockg6/pid]

5b4995fac356: Pushed

eeed011d30f4: Pushed

1dcd23cba987: Layer already exists

3f5111fd7752: Layer already exists

Gracias a la estructura en capas de las imágenes (apartado 3.6.2.1) se optimiza el ancho de banda, no siendo

necesario subir o descargar las capas de las imagenes que no hubieran cambiado.

Figura 4-15. Imágenes en Docker Hub

4.3.3 Despliegue en un clúster de nodos distribuidos

Todo el trabajo realizado hasta ahora con contenedores se ha desarrollado en una única máquina Docker. El

funcionamiento del PIDS en un entorno de producción exige dotarlo de resiliencia, con capacidades de escalado

ágil para atender picos de demanda que no impacten en el rendimiento de los servicios, y actualizaciones

continuas que no impliquen interrupciones innecesarias. Todo ello sin menoscabo de una administración

simplificada. En el contexto de los contenedores, estos requisitos se satisfacen mediante una plataforma de

orquestación de servicios multi-contenedor.

El objetivo último de este apartado será utilizar Docker en modo Swarm para desplegar el stack de servicios

definido en el apartado anterior con tareas replicadas y distribuidas en un clúster de nodos. Para el

aprovisionamiento de los nodos se utilizarán instancias EC2 de Amazon Web Services (AWS), creadas y

administradas mediante la herramienta Docker Machine (apartado 3.6.3.2). Son, por tanto, prerrequisitos para

seguir avanzando estar inscrito en una cuenta de AWS, tener instalado Docker Machine y, como se vio en el

apartado anterior, disponer de las imágenes del proyecto en un repositorio de Docker Hub.

Según lo explicado en el apartado 3.6.4.2, los nodos de un clúster Swarm tendrán uno de los dos roles posibles,

Manager o Worker. Los nodos Workers contienen las tareas de los servicios mientras que los Managers se

encargan de la gestión del clúster, monitorizando el estado y planificando la ejecución de las tareas. Si no se

especifica lo contrario, un Manager puede actuar al mismo tiempo como Worker dentro del swarm.

En el escenario de partida que se propone, el clúster estará constituido por cuatro nodos, un Manager y tres

Page 124: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

102

Workers. Es importante reseñar que con un solo Manager se corre el riesgo de perder la capacidad de gestión

del clúster en caso de que el nodo se viese comprometido, aunque las tareas que estuvieran activas continuarían

ejecutándose. No obstante, esta arquitectura se plantea con fines expositivos, para posteriormente demostrar

cómo se puede promover o degradar los nodos en el swarm.

Nota: la mayoría de las herramientas de orquestación, como Docker en modo Swarm, usan el algoritmo de

consenso Raft entre los nodos Managers para poder mantener el estado del clúster con cierta tolerancia a fallos

y poder seleccionar un nuevo Manager líder en caso del fallo. De manera general, el algoritmo viene a

recomendar un número impar no elevado de nodos Managers.

4.3.3.1 Aprovisionamiento

Antes de desplegar las instancias EC2 que representen los nodos del clúster, hay que acceder a la cuenta de AWS

para crear un usuario IAM administrador y generar la clave de acceso del usuario, ya que para crear máquinas

en AWS con Docker Machine hay que proporcionar los datos Access Key ID y Secret Access Key de la clave.

Ambos parámetros se pueden almacenar en el fichero ~/.aws/credentials, donde Docker Machine busca por

defecto las claves de acceso para que no será necesario especificarlas cada vez que se ejecute el comando de

creación de nuevas instancias.

A través de Docker Machine se crearán los cuatro nodos del clúster, con Docker Engine instalados en ellos.

Todos los nodos tendrán las mismas características, especificadas en el momento de la instanciación con el

siguiente comando:

$ docker-machine create -d amazonec2 \

--amazonec2-instance-type "t2.micro" \

--amazonec2-security-group "docker-machine" \

--amazonec2-zone a \

--amazonec2-region eu-west-1 \

--amazonec2-iam-instance-profile "rexrayrole" \

--amazonec2-root-size 8 nodo1

Running pre-create checks...

Creating machine...

(nodo1) Launching instance...

Waiting for machine to be running, this may take a few minutes...

Detecting operating system of created instance...

Waiting for SSH to be available...

Detecting the provisioner...

Provisioning with ubuntu(systemd)...

Installing Docker...

Copying certs to the local machine directory...

Copying certs to the remote machine...

Setting Docker configuration on the remote daemon...

Checking connection to Docker...

Docker is up and running!

To see how to connect your Docker Client to the Docker Engine running on this

virtual machine, run: docker-machine env nodo1

Para aprovisionar los nodos en AWS, hay que especificar al menos el driver amazonec2, una región AWS

apropiada y un nombre para el nodo. El driver incluye una amplia variedad de opciones [34] para configurar

diferentes características de procesamiento, red, seguridad, etc. Aunque se ha indicado explícitamente en el

comando, las instancias EC2 que se crean por defecto, y están incluidas en la capa gratuita de AWS, son del tipo

t2.micro, provistas de 1 CPU y 1 GB de memoria. El tamaño del disco para las instancias se ha fijado a 8GB.

Son prestaciones suficientes para probar el funcionamiento del servidor PIDS en circunstancias de carga de

trabajo moderadas.

Page 125: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

103

103

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Mediante la opción --amazonec2-iam-instance-profile se especifica el perfil de instancia asociado a la instancia

EC2. El perfil de instancia contiene un rol definido que otorga permisos temporales a las aplicaciones que se

ejecutan en la instancia EC2, sin necesidad de tener que indicar credenciales. Sobre este punto se hablará más

adelante, en el momento que se vaya a crear el volumen de persistencia para la base de datos.

Por limitaciones que también se verán en los sucesivos puntos, todos los nodos deben crearse en la misma región

y zona de disponibilidad, si bien no es un escenario óptimo en términos de continuidad y tolerancia a fallos. La

región seleccionada ha sido Irlanda (eu-west-1). Esta decisión viene influenciada, en parte, por la obligación de

garantizar el cumplimiento de ciertas demandas legales en materia de protección de datos referidas a la ubicación

de los datos.

Como no se ha especificado lo contrario, el nodo se despliega en la VPC por defecto con una AMI AWS de

Ubuntu 16.04 TLS.

En la salida del comando se pueden comprobar las acciones realizadas, como la creación de la máquina virtual,

la generación de los certificados TLS para comunicación segura con las máquinas, o la configuración del

demonio de Docker. Asumiendo que se tiene un cliente Docker instalado, al final de la salida se dan las

indicaciones de cómo conectarlo con la máquina Docker remota: el comando eval $(docker-machine env nodo1)

establece las variables de entorno necesarias para apuntar la CLI de Docker local al Docker Engine remoto.

Los cuatro nodos creados en el proyecto se nombrarán como manager-01, nodo-02, nodo-03 y nodo-04. La

salida de docker-machine ls proporciona información general del estado de los nodos, como el nombre del nodo,

el driver con el que fue generado, la URL de administración, la versión de Docker instalada o los errores en la

máquina.

Nota: la columna ACTIVE marca con un * el nodo que está "activo", es decir, aquel al que la CLI de Docker

local está apuntando, mediante la variable de entorno DOCKER_HOST.

$ docker-machine ls

NAME ACTIVE DRIVER STATE URL SWARM DOCKER

manager-01 * amazonec2 Running tcp://34.2.2.5:2376 v18.03.0-ce

nodo-02 - amazonec2 Running tcp://34.4.7.8:2376 v18.03.0-ce

nodo-03 - amazonec2 Running tcp://34.44.9.19:2376 v18.03.0-ce

nodo-04 - amazonec2 Running tcp://34.2.60.20:2376 v18.03.0-ce

Nota: al no tener una IP pública persistente en AWS puede ocurrir que, por ejemplo, al parar (docker-machine

stop <nodo>) y arrancar de nuevo los nodos, las direcciones IP de los nodos cambien. En esta situación, cuando

se intentasen establecer las variables de entorno del cliente Docker para conectar con el Docker Engine de una

de las instancias EC2, se produciría un error indicando que los certificados de conexión no son válidos. Para

regenerar los certificados hay que ejecutar el comando docker-machine regenerate-certs <nodo>

4.3.3.2 Inicio en modo Swarm

Una vez creados los cuatro nodos AWS del clúster, hay que conectar la CLI de Docker con el nodo de asumirá

el rol de Manager para iniciar el Swarm con el comando:

$ docker swarm init --advertise-addr <Manager_Private_IP/network_interface>

Page 126: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

104

El comando es el mismo que el usado en el punto anterior previo a la creación de secretos, pero añadiendo la

opción --advertise-addr que especifica la dirección IP o interfaz de red que utilizará internamente, en las

comunicaciones entre Managers y en la red overlay. Esta opción sólo es obligatoria si la máquina tiene varias

interfaces de red, aunque siempre es recomendable indicarla para mayor aclaración.

La salida del comando declara el nodo como primer Manager del swarm y proporciona instrucciones de cómo

añadir nuevos nodos al swarm, tanto Workers como Managers, a partir de la validación de los respectivos tokens

de ingreso (apartado 3.6.4.3).

Como paso previo a la ampliación del clúster es preciso habilitar el tráfico de gestión y comunicación entre los

nodos que van a formar parte del swarm. Al crear las instancias EC2 con Docker Machine, se crea un grupo de

seguridad denominado "docker-machine", que únicamente tiene permitido el tráfico entrante por los puertos

22/tcp, para el acceso por SSH, y 2376/tcp, para la comunicación remota entre cliente y servidor Docker. No

obstante, es necesario editar el grupo de seguridad para igualmente permitir las comunicaciones internas del

clúster en los siguientes puertos:

2377/tcp Tráfico de administración del clúster

7946/tcp-udp Tráfico de comunicación entre nodos, para el servicio de

descubrimiento de contendores

4789/udp Tráfico de administración del clúster

Figura 4-16. Grupo de seguridad

Con el grupo de seguridad configurado, se añadirán los restantes nodos como Workers del swarm. El token de

adhesión, como se trató en el apartado 3.6.4.3, se componen de dos partes separadas por un guion: un hash del

certificado de la CA que se utiliza en el clúster para la conexión TLS entre nodos, y una clave única del clúster

para cada rol. De esta forma, permite al Manager validar al nodo que solicita el registro en el clúster, y confirmar

al nuevo nodo el ingreso en el swarm correcto a partir del certificado de la CA. En caso de no haber anotado el

token específico para los nodos Workers al iniciar el swarm, se puede recuperar desde manager-01 con el

comando docker swarm join-token -q worker. Este token junto con la IP del Manager, anunciada en la opción -

-advertise-addr del arranque del swarm, son los parámetros de entrada para el comando de unión al clúster.

Dicho comando debe ejecutarse desde cada futuro nodo miembro del swarm.

Page 127: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

105

105

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

$ eval $(docker-machine env nodo-0X)

$ docker swarm join –token <Worker-token> \

--advertise-addr <Worker_Private_IP> \

<Manager_Private_IP>:2377

Los pasos anteriores se tienen que repetir en nodo-02, nodo03 y nodo-04.

Habiendo apuntado de nuevo el cliente Docker al nodo Manager, el comando docker node ls lista los nodos que

forman el clúster, indicando su nombre, estado (ready | unknown | down | disconnected), disponibilidad para

contener tareas (active | pause | drain), y estado de los nodos Manager en el consenso Raft (leader | reachable

| unavailable).

$ eval $(docker-machine env manager-01)

$ docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS

kulpaj8oqkbdt2kd… * manager-01 Ready Active Leader

ma8bsssognf3nnnf… nodo-02 Ready Active

rom4i4utaszvvk3o… nodo-03 Ready Active

6g0x07xv6ijru71w… nodo-04 Ready Active

En este instante, el clúster está formado por un nodo Manager y tres nodos Workers. Suponiendo el requisito de

hacer el clúster más tolerante a fallo, se podrían promover como Managers los nodos nodo-02 y nodo-03 a

través del comando docker node promote < nodo>. La gestión de los roles debe hacerse desde el nodo Manager.

Volviendo a consultar el estado del clúster, se comprueba que nodo-02 y nodo-03 se han actualizado a Managers

"alcanzables" (reachable). Aun sin ser el Manager líder del swarm, desde cualquiera de estos nodos se podría

actuar sobre cualquier otro Manager, e incluso llegar a degradar al nodo manager-01 a Worker con el comando

docker node demote manager-01.

$ eval $(docker-machine env manager-01)

$ docker node promote nodo-02

Node nodo-02 promoted to a manager in the swarm.

$ docker node promote nodo-03

Node nodo-03 promoted to a manager in the swarm.

$docker node ls

ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS

kulpaj8oqkbdt2kdtf… * manager-01 Ready Active Leader

ma8bsssognf3nnnfxd… nodo-02 Ready Active Reachable

rom4i4utaszvvk3ohl… nodo-03 Ready Active Reachable

6g0x07xv6ijru71wur… nodo-04 Ready Active

$ eval $(docker-machine env nodo-02)

$ docker node demote manager-01

Manager manager-01 demoted in the swarm.

Page 128: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

106

Estas actualizaciones se realizan a efectos de representar la capacidad de adaptación del clúster a cada

circunstancia o necesidad. Para continuar con el apartado, se vuelve a restablecer la configuración del swarm al

estado anterior de este planteamiento.

4.3.3.3 Persistencia multi-nodo

El servicio de base de datos que compone el stack del PIDS es un servicio stateful que requiere del

almacenamiento persistente de la información, por lo que será conveniente montar un volumen externo con

nombre. Sin embargo, en la arquitectura clúster actual, el reto es que el volumen debe estar accesible a todos los

nodos, ya que podría planificarse la ejecución de tareas del servicio de base de datos en cualquiera de ellos. Este

problema ya fue discutido en el apartado 3.6.4.4, donde se planteaban varias estrategias para persistir la

información de la base de datos, como definir restricciones en el stack que fuercen la planificación de las tareas

de base de datos siempre en el mismo nodo que presenta el volumen, con el inconveniente de condicionar la

continuidad del servicio a la disponibilidad del nodo en cuestión. Finalmente, la solución adoptada ha sido definir

un volumen EBS (apartado 3.5.1) en la misma VPC AWS, gestionado con el driver de REX-Ray (apartado

3.6.4.4), de modo que cualquier nodo del clúster pudiera acceder a los datos.

El driver de almacenamiento de REX-Ray no viene integrado con Docker, por lo que tiene que instalarse y

configurarse en cada uno de los nodos del clúster. La instalación agrupará los componentes cliente y servidor de

REX-Ray en todos los nodos, siguiendo un modelo descentralizado de gestión de los volúmenes descrito en el

apartado 3.6.4.4. La forma más sencilla de distribuirlo es mediante el plugin REX-Ray para Docker [35], que se

configura mediante variables de entorno en el mismo momento de la instalación:

$ docker plugin install rexray/ebs<:version> \

EBS_ACCESSKEY="" \

EBS_SECRETKEY="" \

EBS_REGION=eu-west-1a

El nombre del driver del volumen incluye también el nombre de la plataforma de almacenamiento en el formato

rexray/<storage_platform>. Para el proyecto, REX-Ray se encargará de la gestión de un volumen montado

sobre el servicio EBS de AWS. Omitir la versión del plugin en el nombre es equivalente a especificar la etiqueta

latest (los desarrolladores de REX-Ray aseguran que la versión latest siempre se corresponde con la versión más

reciente y estable del plugin).

Los parámetros de configuración indican el tipo de sistema de ficheros a usar, la ruta de datos dentro del volumen

y permisos asignados, valores de reintentos y tiempos de espera antes de determinar un fallo, etc. Todos son

opcionales a excepción de las variables EBS_ACCESSKEY y EBS_SECRETKEY que contienen las credenciales

de AWS con permisos suficientes para que REX-Ray pueda realizar llamadas a la API AWS. El driver EBS de

REX-Ray utiliza la librería AWS SDK oficial, por lo que soporta varias formas de proporcionar credenciales de

acceso. En este caso las variables anteriores están vacías porque, si se vuelve al momento de la creación de las

instancias EC2, se había declarado un perfil de instancia con un rol IAM personalizado, denominado rexrayrole,

asociado a los nodos del clúster. Así, se facilitan a las instancias EC2 credenciales temporales que REX-Ray

podrá utilizar para realizar las acciones sobre recursos AWS definidas en el rol, y sin necesidad de distribuir

ningún tipo de clave de acceso de largo plazo.

La creación del rol rexrayrole es un paso previo al aprovisionamiento de instancias EC2. Desde la consola de

administración de AWS, el rol se crea en la consola de IAM, seleccionando el tipo de rol AWS Service y el

servicio EC2. A continuación se le vincula una política personalizada (administrada por el cliente) que define

los permisos mínimos requeridos por REX-Ray para crear, montar, desmontar y gestionar los puntos de montaje

EBS. El siguiente fichero JSON describe la política que otorga acceso a las APIs de AWS necesarias:

Page 129: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

107

107

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

RexRay_policy.json

{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "ec2:DetachVolume", "ec2:AttachVolume", "ec2:CopySnapshot", "ec2:DeleteSnapshot", "ec2:ModifyVolumeAttribute", "ec2:DescribeInstances", "ec2:DescribeTags", "ec2:DescribeSnapshotAttribute", "ec2:CreateTags", "ec2:DescribeSnapshots", "ec2:DescribeVolumeAttribute", "ec2:CreateVolume", "ec2:DeleteVolume", "ec2:DescribeVolumeStatus", "ec2:ModifySnapshotAttribute", "ec2:DescribeAvailabilityZones", "ec2:DescribeVolumes", "ec2:CreateSnapshot" ], "Resource": "*" } ] }

Nota: al crear el rol con la Consola de administración de AWS, automáticamente se crea el perfil de instancia

con el mismo nombre. Si se hubiera usado AWS CLI, habría que crear explícitamente el perfil de instancia y

añadirle el rol.

Otra variable que es importante especificar en la instalación del plugin de REX-Ray es la referida al parámetro

region, que representa la región y zona de disponibilidad AWS donde va a aprovisionarse el volumen EBS. Hay

que recordar que el ámbito del almacenamiento EBS es la zona de disponibilidad, es decir, sólo será visible por

aquellas instancias desplegadas en la misma zona de disponibilidad. Igualmente, en caso de un fallo inesperado

el volumen sólo puede replicarse dentro de dicha zona de disponibilidad. Esta limitación de EBS es la que ha

obligado a distribuir los nodos en una única zona de disponibilidad. Un caso idóneo para la redundancia de los

servicios hubiese sido distribuir los nodos Manager en un mínimo de tres zonas de disponibilidad para mitigar

cualquier fallo que afectase a una zona completa.

Los valores por defecto del resto de variables para la configuración del driver EBS de REX-Ray son suficientes

y adecuados.

Con REX-Ray instalado en todos los nodos, ya se puede crear el volumen externo para la persistencia de los

datos desde un nodo Manager:

$ eval $(docker-machine env manager-01)

$ docker volume create --driver=rexray/ebs \

--name=dbdata --opt=size=5

Page 130: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

108

El parámetro opt=size=5 indica que el volumen de datos tiene un tamaño de 5GB.

En el fichero de descripción del stack el volumen de datos dbdata estará declarado como external.

4.3.3.4 Despliegue del stack

Son pocas las modificaciones a aplicar sobre el último fichero de descripción del stack para adaptarlo al nuevo

entorno de nodos distribuidos. Lo más relevante es la adición de la opción deploy en cada uno de los servicios

para especificar parámetros de configuración relacionados con la implementación y la ejecución de los

servicios.

pid-compose_stack.yml

version: '3.4' services: db: image: dockg6/pid:db.20 volumes: - dbdata:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD_FILE=/run/secrets/postgres-pass - PID_DB=PID - PID_USER=ibatis - PID_PASS_FILE=/run/secrets/pid-pass deploy: placement: constraints: - node.labels.db == true networks: - pid-network secrets: - postgres-pass - pid-pass webApp: image: dockg6/pid:webApp.20 ports: - "8080:8080" depends_on: - db deploy: replicas: 4 update_config: parallelism: 2 delay: 10s failure_action: rollback networks: - pid-network secrets: - source: pid-file target: pidfile.properties visualizer: image: dockersamples/visualizer:stable ports: - "9000:8080" stop_grace_period: 1m30s volumes:

Page 131: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

109

109

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

- "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] resources: limits: cpus: '0.20' memory: 100M reservations: cpus: '0.10' memory: 50M

networks: pid-network: external: true

volumes: dbdata: external: true

secrets: pid-file: file: ./webApp/data/secrets/pidfile.properties postgres-pass: external: true pid-pass:

file: ./db/data/secrets/pid-pass

En el caso del servicio webApp, al ser un servicio "replicado" (modo por defecto, por lo que no necesita ninguna

opción de configuración -- otro modo, por ejemplo, sería global que implicar desplegar una tarea por cada nodo

del swarm --), con la sub-opción replicas se especifica el número de tareas del servicio que se ejecutarán en los

nodos el swarm. La estrategia de planificación de tareas en modo Swarm, denominada "spread", se basa en la

evaluación de los recursos disponibles en los nodos del clúster. Los criterios que sigue el planificador del clúster

a la hora de desplegar una nueva tarea serían: la nueva tarea será planificada primeramente en un nodo que no

estuviera ejecutando ninguna tarea del mismo servicio, independientemente del número de tareas de otros

servicios en ejecución. Si todos los nodos tienen al menos una tarea del servicio, el planificador selecciona el

nodo con menos tareas del servicio. Por último, en caso de coincidencia, ya tendría en cuenta la valoración

general de las tareas que estuvieran ejecutándose en cada nodo. Es la forma que tiene de garantizar la alta

disponibilidad de los servicios. La estrategia de planificación no sólo se aplica en caso de escalado de los

servicios sino también para preservar el "estado deseado" declarado para los servicios cuando se produce algún

fallo inesperado en las tareas, nodos u otros elementos de infraestructura. Si algún componente del clúster falla,

Swarm intenta restaurar las tareas de servicio afectadas al estado predefinido mediante la planificación de nuevas

tareas que serán desplegadas conforme a la estrategia descrita.

La sub-opción udpate_config determina el comportamiento del servicio replicado durante la aplicación de una

actualización del servicio, como por ejemplo la modificación de la imagen en la que se basa un servicio. El

funcionamiento predeterminado es actualizar una tarea del servicio, parándola y volviéndola a iniciar con la

configuración actualizada. Hasta que no se encuentre en estado "running", el proceso no prosigue con las

sucesivas tareas del servicio. En el stack se ha cambiado este comportamiento en el servicio webApp para

actualizar simultáneamente las tareas en grupos de dos (parallelism: 2), con un tiempo de espera de 10 segundos

entre cada grupo de tareas (delay: 10s), y que fuerce la marcha atrás en caso de fallo (failure_action: rollback).

El servicio db sólo tendrá una tarea en el swarm; sin embargo, se impone una restricción (constraints) que limita

la planificación de la tarea únicamente en los nodos del clúster que fueron etiquetados con el atributo

personalizado node.labels.db. Por tanto, es necesario que, antes de desplegar el stack, se hayan etiquetado

convenientemente aquellos nodos donde se pueden desplegar las tareas del servicio. Una etiqueta es un par de

clave-valor que se utiliza para aplicar metadatos a objetos Docker, en este caso a nodos. En el proyecto, la tarea

del servicio de base de datos sólo se podrá planificar en los nodos manager-01 y nodo-02, los cuales habrá que

actualizar para añadirles la etiqueta db correspondiente:

Page 132: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

110

$ eval $(docker-machine env manager-01)

$ docker node update --label-add db=true manager-01

$ docker node update --label-add db=true nodo-02

$ docker node inspect --format '{{ .Spec.Labels }}' self

map[db:true]

Nota: el volumen vinculado al servicio db está soportado por el sistema de almacenamiento Amazon EBS. Un

volumen EBS sólo se puede montar sobre una única instancia EC2, siendo éste el principal motivo por el que

el servicio sólo tiene una réplica. No obstante, se considera satisfecho el objetivo de ofrecer unas garantías

básicas de continuidad, que se ha logrado mediante la persistencia de la información en un volumen externo y

la posibilidad de adjuntarlo sin intervención manual en el nodo del clúster donde se hubiera restablecido el

servicio ante una contingencia en la infraestructura.

Se podrían estudiar alternativas para escalar horizontalmente el servicio de base de datos como montar un

volumen compartido EFS y complementarlo con un sistema de control de concurrencia en PostgreSQL, pero

queda fuera del alcance del proyecto.

Si por cualquier circunstancia (por ejemplo, el conflicto con otras restricciones o por falta de recursos) la tarea

no pudiera planificarse en ninguno de los nodos sobre los que tiene impuesta la restricción, permanecerá en un

estado "pending" hasta el momento en que sea posible desplegarla.

Docker en modo Swarm también incluye algunos atributos predefinidos basados en metadatos implícitos de los

nodos o Docker Engine que se pueden usar para establecer restricciones sobre la planificación de las tareas de

los servicios. Así, el servicio visualizer del stack tiene impuesta la restricción de que sus tareas asociadas sólo

puedan desplegarse en nodos Manager, a partir del atributo node.role. Visualizer [36] es un proyecto de código

abierto que se despliega como servicio para poder monitorizar el estado del swarm. Con él que se puede

visualizar vía Web un diagrama de los nodos que componen el clúster, las tareas de los servicios que se ejecutan

en cada nodo y la representación gráfica del estado de todos los componentes. No tiene ninguna influencia sobre

el servidor PIDS, pero ayudará a comprobar visualmente lo que sucede en el swarm durante algunas pruebas de

simulación.

Dado que el servicio visualizer solo puede desplegarse en nodos Manager, es conveniente establecer

restricciones de recursos para la CPU y memoria que puede consumir, y evitar cualquier riesgo de inanición de

recursos que impida al Manager desempeñar las operaciones de gestión del swarm. Al especificar un límite de

CPU y memoria (limits) se garantiza que las tareas del servicio no van a consumir más de los recursos definidos

(en este caso, las tareas no pueden usar más de un 20% de CPU y 100MB de memoria). Por el contrario, también

se han reservan recursos dedicados a cada tarea del servicio dentro de los nodos donde se ejecuten (un 10% de

la CPU y 50MB de memoria). Al igual que ocurre con el resto de restricciones, si no es posible planificar una

tarea porque se hubiesen reservado más recursos de los disponibles en los nodos del clúster, la tarea pasará a un

estado "pending" mientras no se liberen los recursos mínimos.

El comando para el despliegue del stack es el mismo que en el caso anterior, donde el swarm estaba compuesto

por un único nodo. En esta ocasión se le ha añadido la opción --with-registry-auth para enviar detalles de

autenticación de Docker Hub y que los nodos de AWS puedan descargar las imágenes de los servicios desde el

repositorio privado, a excepción de la imagen del servicio visualizer que la descargará de su repositorio oficial

público.

$ eval $(docker-machine env manager-01)

$ docker stack deploy --with-registry-auth -c pid-compose_stack.yml pidreg

Page 133: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

111

111

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Para poder consumir los servicios desde el exterior se había declarado la publicación de los puertos 8080/tcp

para el servicio webApp y el puerto 9000/tcp para visualizer (mapeado al 8080/tcp). Según se explicó en el

apartado 3.6.4.3, cuando en modo Swarm se publica el puerto de un servicio, se está publicando para cada nodo

del clúster. Si una petición externa llegase a un nodo en el que no se estuviera ejecutando ninguna tarea del

servicio solicitado, Docker utilizará la propiedad "routing mesh" (apartado 3.6.4.3) para enrutar el tráfico hasta

las tareas que constituyen el servicio. Es necesario modificar el grupo de seguridad "docker-machine" para

permitir el tráfico entrante por esos puertos desde las direcciones IP origen de los clientes del servidor PIDS.

Figura 4-17. Grupo de seguridad – servicios publicados

4.3.3.5 Pruebas funcionales

Con el stack desplegado, se realizarán unas sencillas pruebas de simulación con las que evidenciar el

comportamiento del swarm ante la necesidad de escalado horizontal de los servicios los casos de escalado, o en

caso de fallo de un contenedor o nodo del clúster. Estas características ya se trataron a nivel teórico en el apartado

3.6.4.3.

Partimos de la situación representada en el siguiente esquema que proporciona el servicio visualizer:

Page 134: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

112

Figura 4-18. Visualizer - estado del swarm

Tal y como se puede comprobar en la imagen anterior, la planificación de las tareas en el swarm se ha realizado

conforme a las restricciones configuradas en el stack.

Prueba de escalado

Suponiendo un escenario donde existe la necesidad de atender una demanda creciente de peticiones de servicio

(por ejemplo, por un incremento del número de usuarios) y, por tanto, hay que escalar el número de tareas del

servicio sobre las que repartir la carga para mejorar el rendimiento y la alta disponibilidad del servicio.

Ejecutando el siguiente comando desde el nodo Manager se incrementan las tareas del servicio webApp a 10

réplicas. El planificador del swarm repartirá las tareas en base a la estrategia comentada en el apartado anterior.

$ docker service scale pidreg_webApp=10 --detach=false

pidreg_webApp scaled to 10

overall progress: 10 out of 10 tasks

1/10: running [==================================================>]

2/10: running [==================================================>]

10/10: running [==================================================>] verify: Service converged

Page 135: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

113

113

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Figura 4-19. Visualizer - escalado

Una vez finalizada la necesidad, se puede volver a restablecer el escenario a la situación de partida.

$ docker service scale pidreg_webApp=4 --detach=false

Prueba de replicación / resiliencia

En caso de fallo de algún componente del clúster, como una tarea individual o un nodo completo, el modo

Swarm intentará restablecerlo para mantener el estado deseado declarado del stack. El modo más sencillo de

demostrar esta característica es simular que uno de los nodos deja de estar disponible en el clúster actualizando

su parámetro de disponibilidad en el swarm. La prueba se centra en los cambios sobre la única tarea del servicio

db.

Previamente se confirma que la tarea del servicio db está ejecutándose en el nodo-02.

$ docker service ps \

--format 'table{{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Node}}\t{{.DesiredState}}' \

pidreg_db

ID NAME IMAGE NODE DESIRED STATE

a9wc9 … pidreg_db.1 dockg6/pid:db.20 nodo-02 Running

Se actualizará el parámetro de disponibilidad del nodo-02 de active a drain para que deje de ejecutar cualquier

tarea.

Page 136: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

114

$ docker node update --availability drain nodo-02

$ docker node ls \ --format 'table{{.ID}}\t{{.Hostname}}\t{{.Availability}}\t{{.ManagerStatus}}'

ID HOSTNAME AVAILABILITY MANAGER STATUS

qw9y7em … * manager-01 Active Leader

qn4t442 … nodo-02 Drain

kuhkvk6 … nodo-03 Active

n7hjbbd … nodo-04 Active

Por las restricciones establecidas en el stack, la tarea del servicio de base de datos sólo podrá replicarse al nodo

manager-01, sobre el que también se montará el volumen dbdata gracias al driver de almacenamiento de REX-

Ray.

$ docker service ps \

--format 'table {{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Node}}\t{{.DesiredState}}' \

pidreg_db

ID NAME IMAGE NODE DESIRED STATE

16s5n … pidreg_db.1 dockg6/pid:db.20 manager-01 Running

8oi89 … \_ pidreg_db.1 dockg6/pid:db.20 nodo-02 Shutdown

Figura 4-20. Propiedades del volumen dbdata – prueba de resiliencia

Aunque se vuelva a cambiar la disponibilidad del nodo-02, los contenedores no se rebalancean al nuevo nodo

automáticamente.

Page 137: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

115

115

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

$ docker node update --availability active nodo-02

$ docker stack ps pidreg

ID NAME NODE DESIRED STATE 16s5 … pidreg_db.1 manager-01 Running 8oi8 … \_pidreg_db.1 nodo-02 Shutdown ufmn … pidreg_webApp.1 nodo-03 Running a8bm … pidreg_visualizer.1 manager-01 Running up5y … pidreg_webApp.2 nodo-04 Running 6qxv … pidreg_webApp.3 manager-01 Running 7i2r … pidreg_webApp.4 nodo-03 Running 7o1n … \_ pidreg_webApp.4 nodo-02 Shutdown

Figura 4-21. Visualizer - cambio de disponibilidad (drain) de un nodo

4.3.3.6 Balanceador de carga

La forma más común de acceder a un servicio del que hay varias tareas replicadas entre múltiples nodos es

utilizando un balanceado de carga externo. AWS provee de un servicio de balanceo de carga, Elastic Load

Balancing (ELB), para actuar como único punto de entrada a los servicios y distribuir el tráfico externo entrante

entre todas las instancias del clúster. Aunque el balanceador direccione el tráfico a un nodo donde no se esté

ejecutando ninguna tarea del servicio en cuestión, el modo Swarm lo entregará a un nodo con una tarea activa

mediante la característica de routing mesh.

Para el proyecto, sólo los servicios webApp y visualizer tienen puertos publicados para tráfico HTTP. Entre las

tres opciones de balanceadores que ofrece ELB, Application Load Balancer (ALB) es el más adecuado para la

arquitectura del stack. Funciona a nivel de aplicación (capa 7) y únicamente para el equilibrio de carga de tráfico

HTTP y HTTPS. ALB requiere que se especifiquen subredes de más de una zona de disponibilidad para dotar

de alta disponibilidad a las aplicaciones, aunque para el caso del proyecto será irrelevante dado que todos los

nodos del clúster se sitúan en la misma zona de disponibilidad.

Page 138: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

116

La creación del balanceador se realizará desde la consola Web de AWS. Durante el asistente de creación se

especificarán los datos que siguen:

• Hay que proporcionar un nombre para el balanceador.

• Estará expuesto a Internet.

• Inicialmente se crearán dos agentes de escucha (listener) para el tráfico HTTP en los puertos 8080 y

9000, del servicio webApp y visualizer respectivamente. Al no haber creado ningún agente de escucha

seguro (HTTPS) se puede omitir el paso de importación de certificados.

Figura 4-22. Agentes de escucha del balanceador

• Se creará un nuevo grupo de seguridad llamado "ELB" asociado al balanceador para permitir el tráfico

entrante por los puertos 8080 y 9000 limitadas a las IP origen que interesen. Posteriormente será

necesario editar el grupo de seguridad "docker-machine" vinculado a los nodos para conceder la entrada

del tráfico que provenga del balanceador.

Figura 4-23. Edición de grupos de seguridad

Page 139: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

117

117

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Nota: ya que de cara a los nodos todo el tráfico entrante tiene como origen el balanceador, también se eliminan

las reglas del grupo de seguridad "docker-machine" que permitían el acceso directo desde un cliente externo.

• Los grupos de destino (target groups) al que el balanceador enrutará las solicitudes entrantes estarán

compuesto por todos los nodos del clúster. El asistente de creación del balanceador sólo da opción a

registrar un grupo de destino para un puerto, aunque al finalizar es posible crear nuevos grupos de

destinos y añadirlos en las reglas de balanceo. En el caso concreto del grupo de destino al que se reenvía

el tráfico del puerto 8080, se configura la comprobación de estado basado en la accesibilidad a la ruta

/pid/services/identifyperson para que el balanceador pueda monitorizar el estado de cada uno de los

servicios situado detrás de él.

Figura 4-24. Creación de grupo de destino

Antes de la completar todos los pasos, hay una página para la confirmación de todos los parámetros de

configuración.

Page 140: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

118

Figura 4-25. Parámetros de la creación del balanceador de carga

Una vez completado el alta del balanceador, se puede crear otro grupo de destino relacionado con el tráfico del

servicio visualizer, en el puerto 9000, y editar las reglas de balanceo para el listener correspondiente de forma

que reenvíe el tráfico a este nuevo grupo de destino. Aunque el servicio está restringido a ejecutarse en los nodos

Manager, se añadirán todos los nodos del clúster al grupo por si a futuro se decidiera promocionar alguno.

Dado que el servicio webApp sólo es consumible mediante una URL específica y con el objetivo de restringir la

superficie de exposición del servicio, se definen reglas de reenvío basado en rutas: el listener para el puerto 8080

direccionará el tráfico en función de la ruta o contexto de la URL. Previamente habrá que crear un grupo de

destino "vacío", es decir, sin ninguna instancia. Las reglas de balanceado se editan de la siguiente manera:

• Una primera regla para reenviar todo el tráfico entrante por el puerto 8080 que coincida con la ruta

/pid/services/* al grupo de destino seleccionado.

• La regla por defecto entregará cualquier tráfico del puerto 8080 al grupo de destino vacío.

Figura 4-26. Reglas de balanceo

Pese a que el balanceador es flexible en cuanto al mapeo de los puertos de escucha y reenvío, por claridad y

comodidad, se han configurado los grupos de destino para que los puertos publicados en el balanceador sean los

mismos a los que reenvía el tráfico.

Page 141: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

119

119

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Figura 4-27. Grupos de destino

4.3.3.7 Servicio Web a través de un canal seguro

La sensibilidad de la información tratada por el servidor PIDS exige aplicar una capa de cifrado que garantice

la integridad y confidencialidad en el tránsito de los datos intercambiados. Para securizar un servicio Web existen

dos opciones:

• La seguridad en el mensaje (SOAP), por ejemplo, con el estándar WS-Security que proporciona

diferentes posibilidades de securización, mediante el uso de Kerberos, SAML, tokens, certificados

X.509, etc. La seguridad se implementa en la capa de aplicación.

• La seguridad en la capa de transporte, por ejemplo, enviando los mensajes sobre el protocolo HTTPS.

El objetivo perseguido en este apartado será cifrar todo el tráfico entre cliente y servidor a través de una canal

seguro HTTPS. El balanceador de carga no se configurará como terminador SSL/TLS, sino que se garantiza la

seguridad punto a punto, entre cliente-balanceador y balanceador-servidor.

La secuencia de cambios realizados en el proyecto para alcanzar este objetivo ha sido:

1.- Obtener la clave privada y certificado de servidor

En el contexto académico y de desarrollo del proyecto, se generará un certificado autofirmado para el servidor

que, aunque no esté acreditado por ninguna autoridad de certificación (CA) reconocida y sirva para garantizar

la identidad del servidor, puede utilizarse para proveedor de una canal de comunicación seguro. El único

requisito será tener instalado el paquete OpenSSL.

Con el siguiente comando, se generan dos ficheros de formato .PEM relativos a la clave privada y el certificado

autofirmado del servidor:

$ openssl req -x509 -newkey rsa:4096 -keyout server-rsa-key.pem \

-out server-rsa-cert.pem -days 365

Generating a 4096 bit RSA private key .................................................................++ ...........................................++ writing new private key to 'server-rsa-key.pem' Enter PEM pass phrase: Verifying - Enter PEM pass phrase: ******** ----- You are about to be asked to enter information that will be incorporated into your certificate request.

Page 142: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

120

What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:ES State or Province Name (full name) [Some-State]: Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]: Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:PIDS Email Address []:

El parámetro -keyout especifica el nombre de fichero de la nueva clave privada, de tipo RSA de 4096 bits

(- newkey). También, el parámetro -out define el nombre de fichero para el certificado autofirmado de salida

(- x509), que tendrá una vigencia de 365 días (-days).

De toda la información solicitada, únicamente se especifica una contraseña para proteger la clave privada y el

Common Name (CN) que, en caso de tener un dominio propio, se correspondería con el nombre de host en la

URL que valida el certificado.

Los ficheros de salida se guardan en el directorio data de webApp, dentro de la estructura de carpetas del

proyecto, para su posterior uso en el despliegue del servicio.

2.- Actualización del endpoint del servicio Web

Tan sólo hay que modificar la URL de localización de los ports en el documento WSDL del servicio Web.

PID.wsdl -- Service: IdentifyPerson

<!-- … --> <wsdl:service name="IdentifyPersonService"> <wsdl:port name="IdentifyPersonPort" binding="tns:IdentifyPersonBinding"> <soap:address location="https://localhost:8443/pid/services/identifyperson"/> </wsdl:port> </wsdl:service>

<!-- … -->

Nota: este cambio en el fichero WSDL empaquetado dentro del WAR obliga a tener que crear una nueva imagen

para el servicio webApp y alojarla en el repositorio privado de Docker Hub para poder usarla en el escenario

de nodos Docker distribuidos.

3.- Actualización del stack

Son varios los cambios aplicados al fichero compose del stack, todos relacionados con el servicio webApp:

• Definición de dos nuevos secretos Docker, server-rsa-key.pem y server-rsa-cert.pem, correspondientes

a los ficheros de la clave y el certificado generados anteriormente.

• Definición de una configuración Docker (Docker Configs) que sobrescribe el fichero de configuración

de Tomcat server.xml [37]en las tareas del servicio webApp. El nuevo server.xml habilita un elemento

Connector para aceptar conexiones HTTPS por el puerto 8443, con soporte del protocolo HTTP/2. Se

configura para usar la clave privada y el certificado proporcionados a través de los secretos del punto

anterior, sin crear un almacén de claves en el servidor donde mantenerlos.

Page 143: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

121

121

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Nota: las configuraciones Docker permiten almacenar información no sensible, como ficheros de

configuración, sin necesidad de tener que copiarla en la construcción de la imagen (dockerfile), usar variables

de entorno o montar un volumen. De esta forma es posible mantener la imagen lo más genérica posible.

Las configuraciones funcionan de forma similar a los secretos, excepto que no se almacenan cifradas ni en

memoria, sino directamente en el sistema de archivos del contenedor.

server.xml

<!-- … --> <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol" maxThreads="150" SSLEnabled="true" > <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> <SSLHostConfig>

<Certificate certificateKeyFile="/run/secrets/server-rsa-key.pem" certificateFile="/run/secrets/server-rsa-cert.pem" certificateKeyPassword="********" type="RSA" /> </SSLHostConfig> </Connector> <!-- … -->

• Publicación del puerto 8443, en lugar del 8080.

• Uso de la nueva imagen base para el servicio.

pid-compose_stack-cert.yml

version: '3.4' services: #... webApp: image: dockg6/pid:webApp.30 ports: - "8443:8443" depends_on: - db deploy: replicas: 4 update_config: parallelism: 2 delay: 10s failure_action: rollback networks: - pid-network configs: - source: server.xml target: /usr/local/tomcat/conf/server.xml secrets: - source: pid-file target: pidfile.properties - server-rsa-key.pem - server-rsa-cert.pem

Page 144: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

122

configs: server.xml: file: ./webApp/data/server.xml secrets: pid-file: file: ./webApp/data/secrets/pidfile.properties postgres-pass: external: true pid-pass: file: ./db/data/secrets/pid-pass server-rsa-key.pem: file: ./webApp/data/secrets/certs/server-rsa-key.pem server-rsa-cert.pem: file: ./webApp/data/secrets/certs/server-rsa-cert.pem #...

4.- Nuevo listener del balanceador

Desde la consola de AWS, es necesario crear un nuevo agente de escucha seguro en el balanceador ALB para

que pueda reenviar las solicitudes HTTPS a las instancias del clúster. Por otro lado, el balanceador utilizará una

conexión cifrada para comunicarse con las instancias, por lo que también es preciso crear un nuevo grupo de

destino al que el balanceador distribuirá el tráfico por el puerto 8443.

Figura 4-28. Grupos de destino para comunicación segura

Durante el proceso se solicita seleccionar el certificado que se utilizará en las conexiones frontend. En este caso,

se importará en el servicio IAM la clave privada y el certificado generados anteriormente, copiando el contenido

con codificación PEM de los ficheros en las casillas correspondientes, que se utilizará para establecer la

configuración de seguridad del listener.

Page 145: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

123

123

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

Figura 4-29. Configuración de agente de escucha seguro

Si no se hubiera configurado previamente, al finalizar la creación del listener aparecerá una advertencia

informando que el grupo de seguridad "ELB" asociado al balanceador no tiene una regla que deje pasar el tráfico

en el puerto de escucha. Así mismo, hay que editar el grupo de seguridad "docker-machine" para permitir el

tráfico entrante desde el balanceador a las instancias.

Figura 4-30. Esquema del stack deplegado en cloud

5.- Actualización del cliente

El cliente debe añadir el certificado autofirmado en su almacén de certificados de confianza o truststore, de

forma que el cliente pueda autenticar al servidor como host de confianza. Este almacén suele localizarse en la

ruta $JAVA_HOME/jre/lib/security con el nombre de fichero cacerts. Esta acción puede realizarse con la

Page 146: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Trabajo desarrollado

124

herramienta keytool incluida en el JDK/JRE de Java. El siguiente comando debe ejecutarse con permisos de

root para agregar el certificado en el almacén de claves:

$ keytool -keystore $JAVA_HOME/jre/lib/security/cacerts -importcert \

-alias pids -file server-rsa-cert.pem

Adicionalmente, Java por defecto verifica que el CN del certificado sea el mismo que el nombre de host de la

URL del servicio Web. Si no coinciden, el cliente del servicio Web fallará con una excepción. Para evitarlo

durante el desarrollo, en el código del cliente se puede establecer como verificador predeterminado un

verificador javax.net.ssl.HostnameVerifier personalizado que anule la comprobación cuando la

dirección IP o nombre de host sea la del endpoint del servicio Web. En esta fase del proyecto, se corresponderá

con la IP externa asignada al balanceador de carga. Para ello, habría que insertar un bloque estático en la clase

principal del cliente Java de la siguiente forma:

Principal.java

public class Principal { static { javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier( new javax.net.ssl.HostnameVerifier(){ public boolean verify(String hostname, javax.net.ssl.SSLSession sslSession) { if (hostname.equals("<direccion_IP / hostname>")) { return true; } return false; } }); } // …

}

Nota: esta solución solo se recomienda para fines de prueba y desarrollo. En entornos de producción, debe

usarse un certificado firmado por una CA de confianza, en cuyo caso no hubiera sido necesario plantear

ninguna de estas modificaciones para el cliente.

4.3.3.8 Automatización del despliegue

Todo el proceso descrito para el despliegue del PIDS en el entorno cloud se ha conseguido automatizar mediante

scripts interactivos desarrollados en bash.

Son prerrequisitos para la ejecución de los scripts:

• Tenerlos ubicados en una carpeta que se encuentre al mismo nivel que el directorio del proyecto

Docker.

• Disponer de las imágenes base para los servicios del stack cargadas en el repositorio de Docker Hub.

Para ello, se ha debido completar la generación del WAR que empaqueta el servicio Web del servidor

PIDS y haber etiquetado las imágenes construidas con la nomenclatura correspondiente.

Page 147: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

125

125

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

• Haber iniciado sesión en Docker Hub con el comando docker login.

• Disponer de las credenciales de AWS (aws_access_key_id y aws_secret_access_key) en el fichero

estándar para Amazon AWS, ubicado en ~/.aws/credentials.

• Haber creado un rol (rexrayrole) específico para otorgar a las instancias declaradas los permisos

requeridos por RexRay.

• Configurar el grupo de seguridad asociado las instancias EC2 de AWS para permitir el tráfico entrante

desde el balanceador de carga, entre instancias y de gestión del clúster por los puertos de comunicación

correspondientes.

• Configurar el balanceador ELB, con los agentes de escucha y grupos de destino necesarios, aunque no

será posible añadir los targets en los grupos de destino hasta que se hayan dado de alta las instancias

del clúster. Así mismo, el grupo de seguridad del balanceador debe permitir el tráfico entrante de los

servicios expuestos, y el certificado auto-firmado del servicio Web tiene que importarse al servicio

IAM.

• Mantener la estructura de carpetas para el proyecto que se ha ido documentando, de forma que los datos

de los servicios, como secretos o configuraciones Docker que hacen referencia a ficheros, estén

disponibles en tiempo de despliegue del stack.

El proceso se ha divido en cuatro scripts, numerados e identificados por su correspondencia con cada una de las

acciones realizadas durante el despliegue en un clúster de nodos distribuidos:

• 01-swarm-build.sh: realiza el aprovisionamiento de los nodos del clúster en AWS, inicia el swarm e

ingresa los nodos Workers y Manager, y añade metadato a los nodos donde estará restringido el

despliegue del servicio db.

• 02-RexRay-install.sh: instala el plugin de Docker de REX-Ray/EBS en cada una de las instancias para

garantizar la persistencia multi-nodo de los datos.

• 03-volume-network-secret-create.sh: crea todos los componentes externos del stack, como el volumen

de persistencia, la red de comunicación a la que se conectan las tareas de los servicios, y el secreto

relativo a la contraseña del superusuario postgres de la base de datos (se crea de forma aleatoria).

• 04-stack-deploy.sh: despliega el stack a partir del fichero pid-compose_stack.yml. Antes del mostrar

información del estado de los servicios, espera 30 segundos, tiempo suficiente para la descarga de las

imágenes de los servicios y despliegue de las réplicas en las instancias del clúster.

La variante 04_2-stack-deploy.sh se diferencia del anterior en que el fichero compose utilizado es el

pid-compose_stack-cert.yml.

Page 148: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación
Page 149: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

127

5 CONCLUSIONES

Con carácter general, a lo largo del proyecto se ha realizado la actualización de un servicio de identificación

de personas. El sistema original, que utilizaba una arquitectura tradicional con un servidor de aplicaciones y un

gestor de base de datos desplegados en un único equipo, se ha migrado a una arquitectura distribuida y con

posibilidad de replicación, que no solo le confiere beneficios directos de estabilidad, escalabilidad y seguridad,

sino que permite acelerar el desarrollo facilitando el control de versiones, el mantenimiento y la reutilización

de componentes. Todo ello propicia el uso e integración de metodologías ágiles en el ciclo de vida de la

aplicación para obtener unos resultados más eficientes y de mayor calidad, al reducir los tiempos de entrega y

la anticipación a errores.

Figura 5-1. Escenario de partida y final

Haciendo un repaso a los objetivos planteados en el inicio del proyecto, se pueden considerar plenamente

satisfechos, si bien las decisiones de diseño tomadas para la consecución de alguno de ellos no han estado exentas

de problemas.

La decisión de usar el framework de persistencia MyBatis simplificó significativamente la programación de la

lógica de persistencia, al tiempo que permitió centrarse en el desarrollo de nuevos métodos del servicio PIDS y

ejecutar operaciones sobre atributos a un nivel de detalle más profundo. Uno de los propósitos que se pretendían

conseguir con el uso del framework de persistencia era segregar la lógica propia del servicio y la de acceso y

tratamiento de la base de datos, de forma que la aplicación se pudiera convertir en un bloque software reutilizable

y completamente independiente del modelo de datos que se emplease. Esta pretensión se ha logrado en su mayor

parte, a excepción de algunas operaciones UPDATE de tipos complejos para los que se definieron métodos

específicos, en lugar de implementarlos como procedimientos almacenados.

Page 150: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Conclusiones

128

128

El desarrollo de la aplicación como servicio Web es lo que garantiza el cumplimiento del requisito fundamental

de integración con otros sistemas sanitarios mediante mecanismos estandarizados de comunicación, tanto a nivel

de canal como de formato. Se toma la determinación de implementarlo como servicio Web SOAP (en el

arranque del proyecto, la mayor parte de los trabajos y estudios relacionados a nivel de interoperatividad técnica

en el ámbito sanitario mostraban una mayor tendencia en el uso del protocolo SOAP), teniendo siempre en

perspectiva el contexto general en el que va a funcionar la aplicación: los sistemas sanitarios presentan un

complejo entramado de relaciones entre distintos agentes, gobernados por una descentralización administrativa.

Este entorno de integración exige funcionar bajo un estándar consolidado y en base a un "contrato" normalizado,

representado por el documento WSDL, donde se especifiquen claramente las operaciones y el tipado de los datos

que se van a intercambiar. Por otro lado, el empleo de un enfoque descendente (contract-first) ha supuesto un

punto adicional de desacoplamiento con el modelo de datos empleado, generándose éste automáticamente a

partir de las herramientas de JAX-WS incluidas en el JDK que toman como parámetro el documento WSDL del

servicio.

Cabe destacar que en un primer planteamiento se llegó a desarrollar el servicio tanto con Apache Axis2 como

con CXF. Finalmente se optó por usar la implementación de referencia de la API JAX-WS, suficiente para

cumplir con las necesidades iniciales de integración que no demandaban extender el servicio con

especificaciones WS-* adicionales. Tampoco se requería compatibilidad con frameworks de desarrollo como

Spring, donde sí podría destacar CXF frente al resto de opciones.

Durante la fase de estudio del proyecto quedaron en evidencia las altas expectativas que se han generado entorno

a la virtualización basada en contenedores. Viendo la cuota de aceptación progresiva que está recibiendo, no

cabe duda de que acabará convirtiéndose en una pieza integral en los entornos de producción de compañías de

todos los tamaños. Son continuas las innovaciones y apuestas que están haciendo los grandes proveedores de

servicios en relación a esta tecnología, que cuenta ya con unas bases sólidas asentadas y un constante crecimiento

de uso entre la comunidad de desarrolladores. Aun a riesgo de quedar desactualizado en poco tiempo por el alto

ritmo de evolución que mantiene, no se ha querido dejar pasar la oportunidad de evaluar su aplicación en el

proyecto y aprovecharse de la sencillez de su modelo declarativo para construir las arquitecturas de servicio. La

mejor baza del uso de contenedores reside en su ligereza y portabilidad, que lo convierte prácticamente en una

herramienta de automatización de despliegue, ideal para integrarse con las filosofías actuales de tipo DevOps.

La naturaleza efímera de los contendores, respaldada por características como la ligereza y rapidez de arranque,

permiten que puedan ser sustituidos fácilmente sin que el funcionamiento del sistema se vea alterado. Sin

embargo, esta tecnología alcanza su mayor potencial combinando los servicios de computación cloud con

herramientas de orquestación de clúster de contenedores, tal y como se ha demostrado en el proyecto, cubriendo

sin esfuerzo los requisitos que se habían fijado respecto al aprovisionamiento de un entorno con prestaciones de

escalabilidad y alta disponibilidad. Una circunstancia que también ha propiciado la simplicidad en el despliegue

es el carácter stateless de la aplicación, a excepción de la necesidad de persistir la información almacenada en la

base de datos, pero que igualmente se ha resuelto cómodamente mediante el uso de un plugin de almacenamiento

para la gestión de un volumen creado sobre servicios de almacenamiento en AWS.

5.1 Líneas de mejora

El ámbito del proyecto contempla un importante número de áreas donde se podrían realizar mejoras o

extensiones del proyecto. Centrándose en el alcance concreto del proyecto, a continuación se plantean diferentes

líneas de continuidad a diferentes niveles:

• A nivel de desarrollo, podría actualizarse el modelo de los tipos de datos utilizado en el servicio al

modelo de referencia de la normativa UNE-EN ISO 13606, estando este requisito fuera del alcance

actual.

En un plano más técnico, el modelo de datos está estructurado de acuerdo a relaciones de tipos

complejos compuestos por colecciones de tipos simples u otros tipos complejos. Este es el mismo

planteamiento que se ha seguido en la composición anidada de las sentencias SQL, al establecerse como

objetivo ampliar las especificaciones de búsqueda y hacer más granular las condiciones de recuperación

de los atributos. Con este enfoque ha sido posible generar una estructura modular para reaprovechar en

las sentencias de los atributos de mayor nivel los bloques de SQL empleados en las sentencias de los

Page 151: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

129

129

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

atributos de más bajo nivel que los componen. No obstante, puede derivar en la ocurrencia del problema

de "N+1 consultas", comentado en el proyecto. La versatilidad y dinamismo que proporciona MyBatis

da la posibilidad de atajar el problema desde diferentes opciones que pueden revisarse. Como ejemplo,

se ha dejado preparada en el paquete del proyecto una consulta basada en ResultMaps anidados que

resuelve el problema y que podría usarse como referencia para hacerla extensible al resto de sentencias.

Otro punto de mejora está relacionado con eliminar los pocos puntos de acoplamiento que han quedado

en las operaciones de actualización de datos, de forma que la lógica del servicio de información

demográfica pudiera entregarse como un paquete totalmente independiente. No se llegó a estudiar a

fondo ni se pudo probar la integración en el proyecto de algunas funcionalidades de MyBatis, como su

capacidad de ejecutar operaciones por lotes (batch updates) con los que es muy probable que se

obtuviera mejores resultados de desacople.

Por otro lado, siguiendo las buenas prácticas de desarrollo software, se podría perfeccionar el

tratamiento de la jerarquía de excepciones o la gestión de los logs para llevar un registro de los sucesos

importantes o de depuración de una aplicación Java.

• A nivel de arquitectura, una vez entendidos los fundamentos de la tecnología de contenedores y las

herramientas de orquestación que los gobiernan, las propuestas de mejora van enmarcadas al despliegue

de los servicios aprovechando las innovaciones continuas que van surgiendo en esta materia. Así, las

mencionadas soluciones de contenedores como servicios (CaaS) que los grandes proveedores de

servicios van agregando a su catálogo permiten unificar y agilizar aún más todo el proceso de creación,

despliegue y entrega.

No ha sido necesario por las características del servicio desarrollado, pero se podría extender la

infraestructura proyectada y dejarla preparada para soportar aplicaciones stateful que requieran

persistencia de sesión. En una arquitectura monolítica compuesta por un par servidores esta necesidad

se puede salvar sin complicaciones usando algún tipo de mecanismo de caché que distribuya la sesión

entre los servidores o mediante balanceadores de carga que redirijan todas las peticiones al mismo

servidor (sticky session). Sin embargo, la idea detrás de los clústeres de contenedores es proporcionar

unas escalas mucho más elevadas, con varios contenedores replicados en el mismo nodo. Una de las

posibles opciones sería implementar dentro del clúster un servicio de balanceo de carga que soporte

sticky sessions con soluciones como Traefik o Docker Flow Proxy.

• A nivel funcional, es imprescindible abordar una estrategia de seguridad desde todas las perspectivas,

dado el ámbito de operación previsto para el sistema y la naturaleza de datos de carácter personal que

se tratan. Los sistemas de información en el sector de la salud están sometidos al desafío de preservar

la privacidad y confidencialidad de los datos personales, circunstancia que además se encuentra

respaldada por importante componente normativo y legal, y que convierte a la protección de los datos

en una prioridad [38].

Al margen de las medidas de carácter organizativo, el marco regulatorio de la protección de datos de

carácter personal europeo demanda la aplicación de medidas oportunas y eficaces en todos los dominios

de seguridad: protección de las comunicaciones, mecanismos de control de identificación y acceso,

mantenimiento de registros de auditoría, análisis de vulnerabilidades (a nivel de aplicación,

configuración y sistemas), bastionado de los sistemas, copias de seguridad, cifrado de los datos en

reposo, etc. Trasladando estas obligaciones al stack tecnológico del servicio de identificación

desarrollado, muchos de estos controles han sido tenidos en cuenta durante la configuración de la

infraestructura en el cloud y en el despliegue del servicio con contenedores como una primera

aproximación para obtener unos niveles de seguridad aceptables, aunque insuficientes en un entorno

productivo real. Sería conveniente reforzarlas y enmarcarlas en una política de seguridad común que las

gobiernen.

Siguiendo en la línea de la seguridad y particularizando en la tecnología de contenedores, aunque

utilizan una serie de técnicas de aislamiento para proteger los contenedores unos de otros y de la

infraestructura subyacente con funciones del kernel como cgroups o namespaces, no están exentos de

problemas de seguridad, siendo uno de los principales motivos que pudieran estar frenando su

Page 152: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Conclusiones

130

130

expansión. Sin embargo, han conseguido importantes avances complementándose con proyectos como

SELinux, AppArmor o Seccomp que bien configurados funcionarían a modo de cortafuegos.

Igualmente, el Centro para la Seguridad en Internet (CIS) tiene publicado un documento de buenas

prácticas sobre la correcta configuración de Docker [39]. La aplicación de estos puntos podría plantearse

como posible proyecto de seguridad.

A nivel de los servicios Web SOAP, una forma óptima de de asegurar la confidencialidad e integridad

durante el intercambio de mensajes sería utilizando un modelo de seguridad de la especificación WS-

Security (WSS) para establecer una capa de autenticación y cifrado de extremo a extermo en el servicio.

Page 153: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

131

131

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

REFERENCIAS

[1] S. Indarte y P. Pazos Gutiérrez, «Estándares e interoperabilidad en salud electrónica: Requisitos para una

gestión sanitaria efectiva y eficiente,» Comisión Económica para América Latina y el Caribe (CEPAL),

Santiago, 2011.

[2] J. Vander Sloten, P. Verdonck, M. Nyssen y J. Haueisen, 4th European Conference of the International

Federation for Medical and Biological Engineering 23-27 November 2008, Antwerp, Belgium (IFMBE

Proceedings), Antwerp: Springer, 2009.

[3] OMG, «Person Identification Service (PIDS) Specification,» 2001.

[4] J. Lewis y M. Fowler, «Microservices, a definition of this new architectural term,» 2014. [En línea].

Available: https://martinfowler.com/articles/microservices.html.

[5] «Contenedores de Windows,» Microsoft, 2 05 2016. [En línea]. Available: https://docs.microsoft.com/es-

es/virtualization/windowscontainers/about/.

[6] T. Brown, «MSDN Magazine,» Microsoft, abril 2017. [En línea]. Available:

https://msdn.microsoft.com/es-es/magazine/mt797649.aspx.

[7] W. Wong, «What’s the Difference Between Containers and Virtual Machines?,» ElectronicDesign, 2016.

[En línea]. Available: http://www.electronicdesign.com/dev-tools/what-s-difference-between-containers-

and-virtual-machines.

[8] «Debian Manpages,» septiembre 2017. [En línea]. Available:

https://manpages.debian.org/testing/manpages/cgroup_namespaces.7.en.html.

[9] Wikipedia, «Chroot,» [En línea]. Available: https://es.wikipedia.org/wiki/Chroot .

[10] M. Russinovich, «Microservices: An application revolution powered by the cloud,» Blog Microsoft

Azure, 2016. [En línea]. Available: https://azure.microsoft.com/es-es/blog/microservices-an-application-

revolution-powered-by-the-cloud/.

[11] «Kubernetes,» [En línea]. Available: https://kubernetes.io/docs/concepts/workloads/pods/pod/.

[12] P. Mell y T. Grance, «SP 800-145. The NIST Definition of Cloud Computing,» National Institute of

Standards & Technology, 2011. [En línea]. Available:

https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-145.pdf.

[13] W3C, «XML Path Language (XPATH) 3.1,» 2017. [En línea]. Available: http://www.w3.org/TR/xpath-

3/ .

[14] «Mybatis reference dcoumentation,» [En línea]. Available: http://www.mybatis.org/mybatis-3/index.html

Page 154: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Referencias

132

132

.

[15] K. L. Nitin, S. Ananya y S. Sangeetha, «iBATIS, Hibernate, and JPA: Which is right for you?,»

JavaWorld, 2008. [En línea]. Available: https://www.javaworld.com/article/2077875/open-source-

tools/ibatis--hibernate--and-jpa--which-is-right-for-you-.html.

[16] «JAX-WS Release Documentation. Tools,» Oracle Java Enterprise Edition, [En línea]. Available:

https://javaee.github.io/metro-jax-ws/doc/user-guide/ch04.html#tools-wsimport-ant-task .

[17] «Creating a Simple Web Service and Clients with JAX-WS,» Oracle Java Documentation, [En línea].

Available: https://docs.oracle.com/javaee/7/tutorial/jaxws001.htm#BNAYN.

[18] «Types Supported by JAX-WS,» Oracle Java Documentation, [En línea]. Available:

https://docs.oracle.com/javaee/7/tutorial/jaxws002.htm#BNAZC.

[19] «Docker Community Edition,» [En línea]. Available: https://www.docker.com/community-edition.

[20] «Docker Enterprise Edition,» [En línea]. Available: https://www.docker.com/enterprise-edition.

[21] «OCI, Open Containers Initiative,» [En línea]. Available: https://www.opencontainers.org/.

[22] «Virtual Extensible LAN,» Wikipedia, [En línea]. Available:

https://es.wikipedia.org/wiki/Virtual_Extensible_LAN.

[23] «IP Virtual Server,» Wikipedia, [En línea]. Available: https://en.wikipedia.org/wiki/IP_Virtual_Server.

[24] «Use overlay networks,» Docker Docs, [En línea]. Available:

https://docs.docker.com/network/overlay/#bypass-the-routing-mesh-for-a-swarm-service.

[25] «Use Docker Engine plugins,» Docker Docs, [En línea]. Available:

https://docs.docker.com/engine/extend/legacy_plugins/#volume-plugins.

[26] «REX-Ray,» [En línea]. Available: https://rexray.readthedocs.io/en/stable/ .

[27] G. McCluskey, «Using Java Reflection,» Oracle, 1998. [En línea]. Available:

http://www.oracle.com/technetwork/articles/java/javareflection-1536171.html.

[28] «MyBatis configuration. Settings,» [En línea]. Available: http://www.mybatis.org/mybatis-

3/configuration.html#settings.

[29] «The Java EE 5 Tutorial: Chapter 17 Binding between XML Schema and Java Classes,» Oracle, [En

línea]. Available: https://docs.oracle.com/cd/E19575-01/819-3669/6n5sg7bj5/index.html.

[30] «JAXB2 Basics,» [En línea]. Available: https://github.com/highsource/jaxb2-basics.

[31] «Introduction to the Standard Directory Layout,» Apache Maven Project, [En línea]. Available:

https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html.

[32] «PostgreSQL official docker container,» [En línea]. Available: https://hub.docker.com/_/postgres/ .

[33] «Tomcat official docker container,» [En línea]. Available: https://hub.docker.com/_/tomcat.

Page 155: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

133

133

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

[34] «Machine drivers. Amazon Web Services,» Docker Docs, [En línea]. Available:

https://docs.docker.com/machine/drivers/aws/.

[35] «REX-Ray EBS plugin for Docker,» [En línea]. Available: https://rexray.readthedocs.io/en/stable/user-

guide/schedulers/docker/plug-ins/aws/ .

[36] «Docker Swarm Visualizer,» [En línea]. Available: https://github.com/dockersamples/docker-swarm-

visualizer .

[37] «Apache Tomcat 8 - SSL/TLS Configuration HOW-TO,» The Apache Software Foundation , 2018. [En

línea]. Available: https://tomcat.apache.org/tomcat-8.5-doc/ssl-howto.html.

[38] R. García, «El Reglamento General de Protección de Datos y su aplicación en el ámbito sanitario,» Revista

de la Sociedad Española de Informática y Salud, nº 127, 02 2018.

[39] «CIS Docker Community Edition Benchmark version 1.1.0,» CIS, [En línea]. Available:

https://www.cisecurity.org/benchmark/docker/.

Page 156: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

Glosario

134

134

GLOSARIO

AENOR: Asociación Española de Normalización y Certificación 3

AMI: Amazon Machine Image 46

API: Application Programming Interface 35

AWS: Amazon Web Services 8

CEN: Comité Europeo de Normalización 3

CIS: Center for Internet Security 132

CLI: Command Line Interface 48

CORBA: Common Object Request Object Architecture 14

CTN: Comité Técnico de Normalización 3

DCOM: Distributed Component Object Model 14

DICOM: Digital Imaging and Communication in Medicine 3

DNS: Domain Name System 30

DTD: Document Type Definition 21

EBS: Elastic Block Store 46

EJB: Enterprise JavaBeans 44

ELB: Elastic Load Balancer 47

FTP: File Transfer Protocol 16

HCE: Historia Clínica Electrónica 1

HTTP: Hypertext Transfer Protocol 16

IAM: Identity and Access Management 46

JAXB: Java Architecture for XML Binding 42

JAX-WS: Java API for XML based Web Services 41

JDBC: Java DataBase Connectivity 39

JDK: Java SE Development Kit 82

JIC: Joint Initiative Council 4

OASIS: Organizarion for the Advancement of Structured Information Standards 17

OCI: Open Container Initiative 48

OMG: Object Management Group 3

ORM: Object Relational Mapper 39

PIDS: Person Identification Service 9

REST: Representational State Transfer 16

RMI: Remote Method Invocation 14

Page 157: Proyecto Fin de Carrera - Universidad de Sevillabibing.us.es/proyectos/abreproy/12428/descargar_fichero/PFC-2428... · Proyecto Fin de Carrera Ingeniería de Telecomunicación

135

135

Diseño y desarrollo de un servicio de información demográfica en entorno Cloud basado en

contenedores

RPC: Remote Procedure Call 14

SDO: Standards Developing Organizations 4

SEI: Service Endpoint Interface 43

SIB: Service Implementation Bean 43

SMTP: Simple Mail Transfer Protocol 16

SOA: Service Oriented Architecture 25

SQL: Structure Query Language 38

TIC: Tecnología de la Información y la Comunicación 1

TSI: Tarjeta Sanitaria Individual 9

UDDI: Universal Description Discovery and Integration 17

VIP: Virtual IP 58

VPC: Virtual Private Cloud 46

W3C: World Wide Web Consortium 15

WS: Web Service 17

WSDL: Web Service Description Language 17

XML:eXtensible Markup Language 2