Arquitectura de sistemas distribuidos TEMA 1 ARQUITECTURA DISTRIBUIDA A ESCALA INTERNET 1. CONCEPTOS PREVIOS Existen muchas definiciones de sistemas distribuidos, aunque la más completa dice así: Un sistema distribuido es una colección de ordenadores autónomos, enlazados por una red de ordenadores y soportados por un software que hace que la colección actúe como un servicio integrado. La escala Internet confiere dificultad a estos sistemas distribuidos, por la gran cantidad de ordenadores y usuarios conectados, por la dispersión geográfica de éstos, por la calidad del servicio, la seguridad, autonomía, porqué algunos ordenadores se conectan y desconectan sin control, etc. A la hora de diseñar un sistema distribuido, deberemos tener en cuenta las siguientes características: Heterogeneidad: Pueden coexistir distintos tipos de dispositivos (ordenadores, PDA, etc) con distintos sistemas operativos, hardware y distinto lenguaje de programación. Seguridad: Puede existir información valiosa para los usuarios que se está compartiendo, se pueden usar técnicas de cifrado para que siga siendo lo más confidencial posible. Escalabilidad: Debemos poder añadir nuevos recursos, usuarios, etc, evitando que se pierda el rendimiento y el control; es especialmente perjudicial la existencia de cuellos de botella que, a la larga, disminuirán el rendimiento del sistema. Fallos: El sistema debe ser capaz de detectar la existencia de fallos, funcionar con el error derivando recursos (tolerar los fallos) y ser capaz de recuperarse completamente cuando el fallo se haya solventado. Concurrencia: Debe permitirse acceder a varios usuarios a un recurso simultáneo (datos) y ser capaz de cambiarlo sin que afecte y de resultados erróneos. Transparencia: Ciertos aspectos del sistema están ocultos a las aplicaciones, como por ejemplo la transparencia de ubicación acceso a un recurso sin saber su ubicación. 2. CLIENTE-SERVIDOR En el modelo cliente-servidor hay dos tipos de procesos, los clientes son procesos que hacen peticiones de servicio y los servidores proveen esos servicios. Hay ejemplos híbridos, como por ejemplo un buscador de Internet, que es servidor de la petición que nosotros podemos hacerle a través de su página web, pero a su vez es cliente de otros servidores de Internet buscando la información para nosotros. Arquitectura multiestrato La funcionalidad está distribuida entre distintas plataformas u ordenadores, y hay tres niveles: interfaz de usuario del sistema, capacidad de procesamiento y gestión de los datos. Dependiendo a qué nivel se sitúen estos tres niveles podemos tener distintos tipos de arquitecturas: 2 · Arquitectura de sistemas distribuidos Arquitectura de dos estratos: La interfaz de usuario está ubicada en el cliente, y la gestión de base de datos en el servidor; la capacidad de procesamiento está repartida tanto entre el cliente como en Arquitecturas multiestrato el servidor. Así se mejora la usabilidad, escalabilidad y flexibilidad de las aplicaciones. Arquitectura de tres estratos: Se sitúa un tercer estrato entre el cliente y el servidor, encargado de la capacidad de procesamiento. Aplicaciones basadas en web Este tipo de aplicaciones son un caso especial de arquitectura cliente-servidor. Cuando un usuario hace clic en un enlace se genera una petición al servidor que pone en marcha el código CGI, Java, etc y que acaba generando como respuesta una página en formato web con todos los datos procesados en el script y que visualizamos directamente en nuestro navegador en formato HTML. La gran ventaja de este tipo de aplicaciones es que son accesibles desde cualquier ordenador que disponga de un navegador web, sin necesidad de incluir más código o instalar más programas en el cliente, y esta facilidad y universalidad ha sido uno de los elementos responsables del boom de empresas en Internet. 3. PUBLICACIÓN-SUSCRIPCIÓN En el modelo cliente-servidor, cada vez que el cliente Publicación-suscripción necesita cierta información, la pide o la busca en el servidor; pero hay servicios en los que esta forma de actuar no es útil. Por ejemplo, si somos un inversos en bolsa y nos interesan las cotizaciones del IBEX 35, no podemos estar constantemente buscando la última cotización y monitorizando si hay cambios o no. En este caso, es mucho más útil la publicaciónsuscripción: un productor de información anuncia la disponibilidad de cierto tipo de información y un consumidor interesado se suscribe para recibir esta información de la que el productor periódicamente le va a proveer. El modo de funcionamiento se detalla en la tabla adjunta y se caracteriza por: Localización: La información no hay que buscarla, ya está localizada. Personalización: Recibimos justo la información que queremos y a la que nos hemos suscrito. Actualización permanente de los datos. Reducción del tráfico: El tráfico en la red se reduce ya que no buscamos ni actualizamos periódicamente los datos como clientes, sino que ya está localizada y se nos envíe (síncrona o asíncronamente) cuando hay algún cambio. 4. DE IGUAL A IGUAL Un sistema de igual a igual (peer-to-peer) se caracteriza por ser un sistema distribuido en el que todos los nodos tienen las mismas capacidades y responsabilidades, y en el que toda la comunicación es simétrica. Ejemplo de estos sistemas son napster, emule, etc, usados frecuentemente para la compartición de ficheros, pero existen otras aplicaciones como la computación distribuida, comunicación, colaboración… Las características de estos sistemas son las siguientes: Arquitectura de sistemas distribuidos · 3 Descentralización: Los distintos iguales (miembros) del sistema son los propietarios y tienen el control de los datos y recursos de su ordenador, no hay ningún nodo que tenga una idea completa del sistema. Escalabilidad: Una consecuencia directa de la descentralización es la mejora de la escalabilidad, ya que se pueden soportar muchas más operaciones que si se tiene que recurrir a un nodo que centralizara las operaciones. Anonimato: Puede haber anonimato de autor (de documentos), de publicador (no se puede identificar quién publicó o introdujo un determinado documento en el sistema), de lector, de servidor (no se puede saber en qué servidores se encuentra un documento), de documento (no se sabe qué documentos tienen almacenados los servidores), de petición. Autoorganización: el sistema crece o cambia su organización sin que esta evolución esté supervisada. Coste de la propiedad: La propiedad compartida reduce el coste de poseer el sistema y los contenidos. Conectividad puntual: Los iguales pueden conectarse y desconectarse del sistema a voluntad. Rendimiento: Suele ser una preopcupación en este tipo de sistemas, se mejora con la reproducción (acerca copias de objetos o ficheros a iguales), uso de memorias caché (reduce la distancia necesaria para obtener un objeto) y encaminamiento inteligente (los iguales que se comunican más frecuentemente que tienen intereses comunes). Seguridad: A través de cifrados multicalave, derechos digitales, cortafuegos… Transparencia y usabilidad: Deben funcionar los sistemas de igual a igual independientemente de la red utilizada, del dispositivo que se conecte, del sistema operativo instalado… Resiliencia a fallos: si falla uno o varios componentes del sistema, éste debe seguir funcionando. Algunos sistemas tienen almacenes temporales que registran las modificaciones o comunicación y cuando el igual vuelve a estar activo, recibe las actualizaciones. En otras ocasiones se encolan los mensajes hasta que los iguales estén disponibles. Interoperabilidad: Hay muchos sistemas de igual a igual, pero actualmente ninguno puede interoperar con otro existente, aunque se dan tímidos avances en este sentido como la red emule y eKad. 5. SISTEMAS DISTRIBUIDOS BASADOS EN EVENTOS El uso de eventos permite que un objeto pueda reaccionar a cambios que han ocurrido en otro objeto. Un componente puede anunciar o difundir uno o más eventos y otros componentes del sistema pueden registrar que están interesados en este tipo de eventos y, cuando un evento se anuncia, el sistema invoca a todos los componentes interesados que estén registrados. Los sistemas basados en eventos tienen dos características principales: son heterogéneos y son asíncronos. Por ello aunque inicialmente se parezcan a los sistemas de publicación-suscripción, no tienen nada que ver, dado que los roles son muy diferentes (en publicación-suscripción están diferenciados, aquí no), la frecuencia de la información es muy variable (mucho mayor en los sistemas basados en eventos) y la cantidad también (más elevada la información por publicación-suscripción que en eventos, que tiende a ser mínima, frecuente, pero mínima). 6. CÓDIGO MÓVIL Los sistemas de código móvil pretender usar la movilidad para cambiar dinámicamente la distancia entre el procesamiento y la fuente de datos o destino de los resultados, así cambiando de ubicación, un componente puede mejorar la 4 · Arquitectura de sistemas distribuidos proximidad y la calidad de las interacciones, reducir el coste de las mismas y así, mejorar la eficacia y la percepción del usuario sobre el rendimiento. Básicamente se trata de ejecutar partes de código en máquinas distintas, tanto enviando el código, los datos o una mezcla de ellos: Evaluación remota: El cliente envía el conocimiento al servidor ubicado en un ordenador remoto, allí se ejecuta el código recibido con los recursos que tiene y se devuelve el resultado al cliente. Un ejemplo práctico sucede entre un procesador de textos y una impresora PostScript. Código bajo demanda: El cliente envía una petición a un servidor remoto para que le envíe el código necesario y el cliente con los datos con los que ya contaba, ejecuta totalmente y obtiene los resultados esperados. En este caso el cliente tiene los recursos, pero no el conocimiento necesario. Un ejemplo son las miniaplicaciones web que bajamos y ejecutamos constantemente desde nuestros navegadores web, pues las bajamos y ejecutamos en nuestro ordenador. Agentes móviles: Una unidad de computación se nueve a un ordenador remoto, y se lleva su estado, la parte de código que necesita y los datos necesarios (si los requiere) para llevar a cabo la tarea. Es una combinación de las dos anteriores. En todos los casos la seguridad es importante, la confidencialidad de los datos, y sobre todo por el hecho de ejecutar código ajeno en nuestro ordenador o enviarlo a otro para que lo ejecute, es por ello que el cliente y el servidor deben ser de mutua confianza. 7. TOPOLOGÍAS DE LOS SISTEMAS DISTRIBUIDOS Centralizada: Es la que estamos más habituados a ver (primera figura de la imagen lateral), un nodo servidor contiene la información y los nodos clientes obtienen la información de este servidor. Es un sistema simple en administración y consistencia de datos, pero es muy vulnerable a fallos. En anillo: Se utiliza cuando un servidor se satura porque tiene muchas peticiones, y consiste en tener un conjunto de servidores conectados entre sí de manera que se coordinen para tener un estado común, balanceando la carga y obteniendo un buen resultado frente a fallos (segunda figura de la imagen lateral). Jerárquica: (tercera figura) Un conjunto de nodos tiene un nodo superior que les ofrece la información que éstos necesitan, si un nodo no tiene la información, la reclama a su inmediato superior. Son sistemas muy escalables y bastante resistentes a fallos, pero con un punto débil: el nodo raíz. Descentralizada: Cualquier nodo se conecta a cualquier otro, como podemos ver en la cuarta figura de la imagen lateral. Son sistemas muy extensibles y muy tolerantes a fallos, pero son difíciles de administrar y suelen ser bastante inseguros. Centralizada y en anillo: Es una topología híbrida, y se comporta como un sistema centralizado, pero el nodo servidor no es un único ordenador, sino que está formado por un conjunto de ellos, así el usuario ve un único punto de conexión pero con las ventajas que ofrece tener un conjunto de ordenadores que responden a las peticiones de los clientes. Es una combinación simple pero potente. Centralizada y descentralizada: Este tipo de topología intenta que cualquier nodo puede relacionarse con cualquier otro, que es la principal desventaja de las topologías descentralizadas. Así con cierta centralización se aporta sencillez a la hora de conseguir coherencia dentro del sistema, aunque sigue siendo difícil de administrar y bastante inseguro. Topologías de los sistemas distribuidos: Centralizada, en anillo, jerárquica, descentralizada, centralizada y en anillo, y centralizada y descentralizada. Arquitectura de sistemas distribuidos · 5 TEMA 2 CONCEPTOS DE SISTEMAS DISTRIBUIDOS Tema 2 Conceptos de sistemas distribuidos 1. La observación de un sistema distribuido 2. Tiempos y relojes 3. Tolerancia a fallos 4. Comunicación en grupo 1. LA OBSERVACIÓN DE UN SISTEMA DISTRIBUIDO Un sistema distribuido está formado por personas, máquinas, procesos, agentes situados en lugares distintos. Puede entenderse de manera abstracta como un conjunto de procesos que cooperan para solucionar un problema intercambiando mensajes. Y éste último punto es el que hace imposible la observación fotográfica de un sistema distribuido, es decir, no es posible poder construir una imagen del sistema en un momento dado, ya que varios procesos nunca se pueden observar a la vez y, por tanto, no se pueden hacer afirmaciones sobre el estado global del sistema. El efecto relativista ocurre en Internet todos los días: velocidad de propagación menor, datos que circulan formando colas y sufriendo retrasos para atravesar routers, datos que se pierden porque una cola rebosa o un bit cambia de valor por error, datos desordenados que tardan en ser procesados por la carga del servidor, etc. 2. TIEMPOS Y RELOJES Es necesario en todo sistema distribuido medir el tiempo y saber con la mayor exactitud el momento en el que ocurrió un evento determinado: es necesario sincronizar el reloj del computador con una fuente de referencia externa. Cada computador tiene su reloj propio, con valor temporal que varía de manera distinta y que requiere un ajuste continuo para que todos los computadores de un sistema tengan un valor de tiempo aproximadamente igual. Por medio de intercambiar mensajes, los relojes de varias máquinas se pueden coordinar entre éstas, teniendo en cuenta el tiempo de ida y vuelta del mensaje, se puede ajustar el reloj local sin dar saltos, es decir, acelerándolo o ralentizándolo durante un período de tiempo hasta que incorpore el ajuste. Así si sabemos el Treal y el Tdespl, los valores para ajustar el reloj de un computador en N ciclo, según el método Christian, serían: A = (Treal – Tdespl) / N B = Tdespl – (1+a) h Además, si en una red local solo hay un servidor al que consultar el tiempo, puede ser problemático en caso de fallos y por eso se suelen usar mecanismos de sincronización con varias referencias de tiempo: el algoritmo de Berkeley permite que una máquina pregunte el tiempo a otra e incorpore los ajustes necesarios con tolerancia a fallos y envía a cada máquina del conjunto el ajuste de reloj que necesite; el protocolo de tiempo en red permite que una máquina puede ajustar su hora por Internet. Otra forma de actuar son los relojes lógicos que en lugar de usar la hora, determinan el orden relativo de ocurrencia de dos eventos; es decir, se trata de contadores de eventos que siempre aumentan y que no tienen relación con el reloj físico. Así cada proceso P tiene un reloj lógico L que se usa para marcar el tiempo virtual en el que se ha producido un evento. Las relaciones importantes entre eventos y relojes lógicos son las siguientes: Procedencia: si dos eventos e1 y e2 se dan ene el mismo proceso P, el orden es claro para todo el sistema e1 e2. El envío de un mensaje ocurre antes de la recepción envio(e1) recepción(e1); y si e1, e2 y e3 son eventos que e1 e2 y e2e3 entonces por transitividad e1e3. Concurrencia: (||) entre eventos, cuando dos no están relacionados por no hay una relación causal 6 · Arquitectura de sistemas distribuidos La ordenación causal de eventos captura en muchos casos la información esencial para describir una ejecución, pero como hay un reloj Lamport para cada proceso, y comparando su valor en dos mensajes que nos llegan, no podemos concluir si uno precede al otro o son concurrentes, para esto se inventaron los relojes vectoriales. 3. TOLERANCIA A FALLOS Podría esperarse que la fiabilidad de un sistema distribuido dependiera de la fiabilidad de sus componentes, pero no es así, ya que un sistema distribuido está formado por componentes que interactúan y nuestro objetivo de funcionamiento es no fallar cuando falla un componente, sino funcionar con componentes averiados o en mantenimiento. Una forma tradicional y sencilla, aunque cara de obtener este objetivo es tener el sistema replicado, aunque es posible obtener tolerancia a fallos a partir de hardware sin replicar y una capa de programas que ofrezcan un modelo de programación y algunos servicios esenciales para programar aplicaciones distribuidas tolerantes a fallos. Varios de estos servicios son los siguientes. La gestión de replicación tiene lugar cuando se replican los datos en varios servidores y es necesario saber quién gestiona qué y como se gestionan estas réplicas. Hay dos tipos de operaciones, las de servidor a servidor (sirven para ajustar el rendimiento, prevenir y reaccionar ante fallos) y las de cliente a servidor que se pueden encontrar varios casos: Copia disponible: (leer uno, escribir todos). Las actualizaciones se aplican a todas las copias, y las lecturas se hacen de cualquier réplica. Votación: Cada réplica tiene uno o más votos, cada operación recolecta votos de las replicas hasta conseguir quórum y, entonces, se aplicará la operación. La detección de fallos puede asumir varios tipos de fallos: Fallo y parada: un proceso funciona bien, y de pronto se para, es el modelo de fallo más fácil de detectar. Funcionamiento erróneo: todo parece ir bien hasta que se empiezan a percibir resultados erróneos; es un fallo peligrado pues es difícil detectar la situación y desde cuando se llevan cometiendo errores. Sistema más lento: todo parece funcionar, pero la velocidad general del sistema va decreciendo paulatinamente. Una manera de simplificar todos estos fallos es disponer una capa de software que vista todos los fallos como si fueran paradas. Así que se trata de preguntar a los procesos para verificar que no están funcionando erróneamente, y si se ralentizan o dan errores, se les considera parados y se les ignora. La gestión de grupos de procesos se hace enviando mensajes a todos los miembros del grupo para comprobar que todo funciona bien, pero existen según el número de miembros varias técnicas: Enviar el mensaje a un proceso que gestiona y grupo y éste se encarga de reenviarlo a todos los miembros; este proceso se convierte en un punto débil, que si falla, falla la comunicación con todo el grupo. El proceso que quiere enviar pide primero la lista de miembros al proceso que gestiona el grupo, y el emisor manda el mensaje a cada destinatario; el problema es que si el número de miembros aumenta o disminuye desde que se pide la lista hasta que se envía el mensaje, la entrega a todos los miembros puede no ser correcta. Arquitectura de sistemas distribuidos · 7 Una lista compartida entre emisores y algoritmo de cardinalidad; los mensajes se entregan cuando el número de miembros no varía y nos aseguramos que todos reciben el mensaje. La entrega de mensajes es esencial para garantizar ciertas propiedades del sistema. Así nos aseguramos de determinar la fiabilidad, orden y latencia. Fiabilidad: Determina qué procesos pueden recibir una copia del mensaje, y cada participante tendrá que guardar información de estado y una copia de los mensajes, para ofrecer atomicidad (a todos los miembros del grupo o a ninguno), fiabilidad (a todos los miembros en funcionamiento), quórum (a una fracción del grupo), intent (a cada miembro del grupo, pero ninguno garantiza haber recibido el mensaje). Orden: Cada receptor tendrá una cola de entregas que reordenará según restricciones: total causal (en el mismo orden a cada uno respetando el orden de causalidad), total no causal (a todos los miembros sin tener en cuenta el orden causal), causal (respetando las relaciones causales), FIFO (en orden desde cada uno, pero los mensajes provenientes de otros pueden llegar en cualquier orden) y desordenado. Latencia: los procesos que se comunican deberán tener en cuenta la latencia elegida para determinar si un mensaje se ha entregado correctamente o no: síncrona (comienza y se completa en tiempo limitado inmediatamente), interactiva (comienza inmediatamente, pero no tiene tiempo limitado), limitada (los mensajes pueden encolarse o retrasarse, pero hay un tiempo límite para recibirlos) o eventual (los mensajes se pueden encolar o retrasar pero no hay tiempo límite para la entrega). Las transacciones en presencia de fallos para saber que se ha ejecutado correctamente y se ha entregado de forma atómica a todos los miembros del grupo puede requerir varias rondas de comunicación: una primera en la que el emisor Transacciones en presencia de fallos propone la operación y recoge el acuerdo de los receptores. Si todos están de acuerdo, el emisor confirma de nuevo a todos que la operación se puede llevar a cabo (o notifica que se cancela) y por último puede haber una tercera ronda en que los receptores pueden confirmar que han podido llevar a cabo la operación y el emisor comunica a todos los receptores que la operación ha ido bien. Con todo ello observamos que la entrega de un solo mensaje a tres destinatarios con ciertas garantías, como en la figura lateral, puede generar mucho más que los tres mensajes que inicialmente podríamos imaginar que se requerirían. 4. COMUNICACIÓN EN GRUPO Una forma segura que evite todos los inconvenientes mencionados anteriormente sería un modelo de cuasisincronía en la que los eventos duran internos, envios, recepciones y cambios de cardinalidad, donde los mensajes fueran de difusión selectiva a grupos de procesos, donde cualquier pareja de procesos recibe los eventos en orden total y causal y donde una difusión selectiva se entrega a todos los miembros: el vento de entrega y recepción concurren al mismo tiempo. Es una imagen bonita pero irrealizable, la cuasisincronía es imposible en presencia de fallos, pues los fallos no se puede programar para que no ocurran durante las entregas; además el sistema avanza paso a paso, tan lento como el más lento de los procesos y una operación que bloquease el sistema, cuando lo desbloquease, seguramente se seguiría de otra que lo volvería a bloquear, por ello es mucho más realizable y realista hablar de sincronía virtual. 8 · Arquitectura de sistemas distribuidos En este orden de cosas se sitúa ISIS, es un entorno de programación de sistemas tolerante a fallos que ofrece este modelo de sincronía virtual, se consigue con ello cierto equilibrio entre velocidad del sistema y tolerancia a fallos. Arquitectura de sistemas distribuidos · 9 TEMA 3 REPRESENTACIÓN DE DATOS Tema 3 Representación de datos 1. Antecedentes: el hipertexto 2. Hojas de estilo HTML 3. XML 4. XHTML 5. XSLT 1. ANTECEDENTES: EL HIPERTEXTO La publicación de páginas mediante HTML ha sido muy útil durante muchos años, pero su principal virtud, que es su publicación por Internet, se convierte tiempo después en su principal defecto, pues quizá nos interesaría optimizar páginas para pantallas de ordenador, pero también para teléfonos móviles, mediante archivos de voz, para dispositivos sin teclado o con pantalla táctil, etc. La familia de aplicaciones XML ofrece varias ventajas en su lugar: EN XML se puede escribir información estructurada independiente de la presentación. Los documentos XML se pueden asociar a información de presentación que puede particularizarse para cada medio de presentación (hojas de estilo). Los documentos XML se pueden transformar en otros documentos XML o de otro tipo. Se pueden expresar operaciones y secuencias de interacción complejas, específicas para comunidades de personas, denominadas vocabularios. 2. HOJAS DE ESTILO HTML Dos de los problemas más importantes que tiene el lenguaje HTML son que la información de formato y estructura está mezclada y que la variedad de maneras aceptables de expresar una marca es elevada, ya que los pequeños errores siguen siendo bien interpretados por la mayoría de los navegadores de Internet. El primer problema se soluciona con las hojas de estilo en cascada (CSS) que podemos aplicar sin problemas en el lenguaje HTML actual; el segundo, en cambio, requiere un nuevo lenguaje más estricto basado en XML: el XHTML. Suele ser recomendable dejar toda la información de estilo de un sitio web completo en u documento aparte, compartido por todos los documentos HTML; así un cambio en el documento de estilo afectará inmediatamente a todos los documentos que usen ese estilo. Se les llama hojas de estilo en cascada o superpuestas porque a un mismo documento se le pueden aplicar varios estilos antes de ser presentado, siendo el orden de aplicación el siguiente: Declaraciones importantes del autor. Declaraciones importantes del lector. Declaraciones normales del autor. Declaraciones implícitas (atributos HTML) del autor. Declaraciones normales del lector. Valores por defecto del agente de usuario (navegador). Estas hojas en cascada crecen y evolucionan con la web, pero a pesar de ello, el lenguaje HTML está limitado desde el comienzo para la representación de páginas web; en éstas y otras muchas situaciones es necesario un lenguaje para representar datos estructurados: el XML. 3. XML El lenguaje XML (extensible markup language) es el formato universal para documentos estructurados y datos en la web. Un documento XML puede ser perfectamente presentado en la web con formato tanto de forma como de contenido, y además una persona o un programa podrán automáticamente obtener datos del mismo que pueden ser de nuevo procesados. 10 · Arquitectura de sistemas distribuidos Por tanto XML puede servir para representar y transportar información estructurada como la que se puede guardar en una base de datos, también sirve para representar información. El XML es más restrictivo que el HTML, pero se permite que diferentes comunidades pueden intercambiar documentos siempre que se pongan de acuerdo en el nombre de los elementos a incluir y la forma de organizarlos; varias organizaciones han definido su propio vocabulario (nombres de elementos y atributos particulares) y conjuntos de restricciones para construir documentos aceptables dentro de su comunidad. También XML puede combinar elementos o atributos definidos por varias comunidades, así el mecanismo de declaración de espacios de nombres permite asociar un prefijo a cada espacio de nombres o incluso definir el espacio de nombres por defecto para no tener que escribir constantemente el prefijo. La función de los esquemas XML es definir y restringir el contenido y estructura de documentos XML expresado en XML y, por tanto, sustituir los DTD (herencia de SGML) por esquemas XML. Un esquema XML resulta bastante más largo que un DTD, pero a cambio, la verificación de los datos es más rigurosa y la exportación e importación de datos es más sencilla para cualquiera que use un procesador de documentos XML que previamente valide el documento contra un esquema. 4. XHTML XHTML es la formulación de HTML 4.01 en lenguaje XML 1.0; el objetivo es reducir la complejidad que supone procesar documentos HTML y que hace difícil incorporar un navegador a un dispositivo de capacidad reducida. Se trata de “limpiar” HTML, de crear una nueva base para modularizar y extender el lenguaje, de facilitar que nuevos dispositivos puedan “navegar” por la web, pero sin romper con HTML. 5. XSLT Es un lenguaje para expresar hojas de estilo; un documento que describe cómo mostrar un documento XML de cierto tipo. Tiene 3 partes: Transformaciones XSL: un lenguaje para transformar documentos XML (representados como una estructura de datos arborescente). El lenguaje de caminos (XPath): un lenguaje de expresiones que usa XSLT para acceder a partes de un documento XML o referenciarlas. Objetos de formato XSL: Un vocabulario XML para expresar el formato de presentación de un documento, que define objetos y propiedades del formato de un documento y sus componentes. El lenguaje XSL es muy extenso y sigue evolucionando. Arquitectura de sistemas distribuidos · 11 TEMA 4 MECANISMOS DE INVOCACIÓN Tema 4 Mecanismos de invocación 1. El mecanismo de invocación remota 2. Codificación de datos para el intercambio 3. Formatos de codificación de datos 4. Invocación de operaciones remotas (RPC) 5. Tipos de protocolos RPC 1. EL MECANISMO DE INVOCACIÓN REMOTA El mecanismo fundamental de construcción de programas se basa en la invocación de trozos de programa entre la memoria y el procesador con la mediación del bus PCI. Resulta tentador extender este modelo para la invocación entre máquinas diferentes y sustituyendo el bus PCI por la red. Sería además ideal que la separación no se notara, que fuese transparente, pero es difícil dado que la red tiene un comportamiento más complejo que el bus interno de un PC: se pierden, desordenan, duplican paquetes y, a veces, la red falla. La separación entre la máquina y el proceso que solicita un servicio y quien realmente lo lleva a cabo da pie a introducir nuevas variantes o parámetros como la arquitectura (tamaño y organización de los datos), lenguaje de programación, sistema operativo de ejecución (puede ser diferente entre las dos máquinas), etc. En general se tratará de pasar toda la información, lo más encapsulada y comprimida posible, pero siendo entendida por las dos máquinas que actúan como cliente y servidor respectivamente. 2. CODIFICACIÓN DE DATOS PARA EL INTERCAMBIO Cualquier mecanismo de invocación remota necesita pasar datos por la red en forma de secuencia de octetos. Obviamente hay que acordar un mecanismo de codificación (el emisor) y una interpretación de los datos recibidos (receptor). El problema es más complejo de lo que parece a priori: hay que definir qué tipos de datos se van a utilizar (enteros, caracteres, reales), el orden en que se van a enviar estos datos, repertorio o juego de caracteres a utilizar. Es decir, hay que representar “en serie” un conjunto de datos que inicialmente no estaban pensados para este tipo de representación y además si es posible, debemos intentar compactarlo tanto como sea posible para disminuir el tráfico en la red y mejorar la velocidad de ejecución. Hay varios formatos para reducir la complejidad y el coste de los datos: Enviar en el formato interno del emisor o transformar los datos en el formato interno del receptor. En cualquiera de los dos casos el problema es complejo pues uno de los extremos no debe hacer nada y el otro debería conocer como representar los datos para cualquier arquitectura, no parece una solución viable. Enviar en forma canónica intermedia que debe ser conocida por cada computador. No conversión si los dos computadores son similares. Es decir en el caso anterior si los dos computadores son iguales, estamos haciendo dos conversiones innecesarias. En el formato del emisor incluyendo una indicación del formato, para que el receptor a la llegada de los mismos, pueda convertirlos. Otro aspecto interesante es el endian, el orden de representación de datos de varios bytes de longitud. Puede ser de dos tipos: Little-endian: el byte menos representativo se guarda en la dirección de memoria menor, son little-endian los Pentium, el sistema operativo Windows y distintos tipos de archivos; su ventaja es que las operaciones matemáticas son más fáciles de hacer porque el primer byte que se encuentran es el más pequeño y a partir de ahí en orden creciente, se van encontrando los siguientes bytes para operar. Big-endian: El byte más significativo se guarda en la dirección de memoria menor. Son de este tipo los procesadores motorola, el superSparc de Sun, el 12 · Arquitectura de sistemas distribuidos sistema operativo Macintosh y sirve para saber rápidamente si un número es positivo o negativo, se guarda tal como se escribe. Cada valor de datos necesita una etiqueta que aporta información para delimitar e identificar el valor, suele indicar el tipo de valor, la longitud o la arquitectura (endian). Otra duda es la codificación textual o binaria; con la primera todo se convierte a texto, es una opción muy legible y se prefiere por su facilidad para analizar por si algo falla, pero tiene el inconveniente que se usan muchos bits de información para expresar algo corto y por tanto la velocidad de ejecución y la transmisión por la red se resienten. Por el contrario, con la codificación binaria no se busca legibilidad, sino eficiencia, minimizando el número de bits que ocupa la información y así minimizando el tiempo de conversión de datos. Para delimitar los elementos a codificar hay varios opciones habituales: Longitud fija: es compacta e inflexible, precisamente el efecto 2000 Formas de delimitar datos se debió a este tipo de codificación. Solo es recomendable para datos que tengan siempre la misma longitud, pues en otro caso o desperdiciamos mucho espacio o corremos el riesgo de no poder expresar algún dato. Por longitud: Se debe conocer la longitud con antelación y así al receptor lo primero que le llega es la medida exacta del dato, lo malo es que el emisor debe recorrer todo el dato para poder enviar esta información lo primero de todo. Delimitada: En lugar de calcular la longitud, se reserva un símbolo para separar datos (en el ejemplo lateral es “;”. Por longitud a fragmentos: Cuando se desconoce la longitud total del dato se utiliza para ser menos lesivo para el emisor; esto posibilita que los datos comiencen a emitirse antes y que el productor pueda ahorrar memoria dedicada a mantener datos preparados para el envío. Como ya hemos dicho anteriormente, para expresar los datos solemos necesitar una etiqueta que distingue su presencia del resto de datos, la longitud del mismo (si no se usan delimitadores) y el valor que tiene. En general, para minimizar la información que se envía por la red podemos usar varios mecanismos: Si todos los datos de un conjunto aparecen siempre y en el mismo orden, la etiqueta se puede omitir. Si la longitud la conocen de antemano los participantes en la comunicación, también se puede omitir. Si los participantes conocen de antemano el valor por defecto que suele tomar el dato, también se puede omitir. 3. FORMATOS DE CODIFICACIÓN DE DATOS Tenemos varios formatos para codificar los datos que estudiaremos a continuación: XML (el único textual, el resto son binarios), XDR, ASN.1, Network data representation, Common data representation y serialización de objetos java. XML Es el único sistema que representa datos en forma textual, no siendo una representación nada compacta (como se ve en la tabla lateral), pero sí que muy informativa y fácil de entender. XML <?xml version=“1.0”?> <methodCall> <methodName>buscar</methodName> <params> <param> <value> <struct> <member><name>nombre</name><value>Juan </value></member> <member><name>edad</name><value><i4> 42 </i4></value></member> </struct></value></param> </params></methodCall> Arquitectura de sistemas distribuidos · 13 External data representation (XDR) Soporta todos los tipos del lenguaje C, define la forma canónica intermedia, no usa etiquetas y utiliza big-endian. XDR Abstract suntax notation 1 (ASN.1) Su formato es [etiqueta, longitud, valor], si ocupa menos de 127 bits, ocupa 1 byte, utiliza big-endian. Network data representation Adoptado por Microsoft para invocación remota binaria; el emisor envía en su orden endian preferido y el receptor se encargará de arreglarlo, las etiquetas se indican en cada mensaje, pero los datos no las llevan. Common Data Representation Common data representation (CDR) Definido en Corba 2.0 permite representar tanto big como little-endian. Los valores se transmiten en el orden del emisor: se envía etiqueta de arquitectura, pero no se envían etiquetas de tipo pues es implícito: el emisor y el receptor ya lo han acordado previamente. Serialización de objetos Java Es específico para el lenguaje Java. En general la ventaja principal de XDR es su simplicidad, pues usa enteros de longitud fija y todos los datos ocupan múltiplos de 4 bytes, los más pequeños se redondean con bits a 0. CDR es más complejo que XDR y permite seleccionar entre big y little endian, lo que permite ahorrar conversiones entre máquinas. ASN.1 es más ineficiente en espacio y codificación; el mecanismo de empaquetado de tipos y longitudes hace que requiera más instrucciones para procesar los datos. Por último, XML ocupa mucho más espacio, el código para (des)codificar es más complejo y lento, pero su forma textual hace que sea muy fácil de depurar. 4. INVOCACIÓN DE OPERACIONES REMOTAS (RPC) La invocación de operaciones remotas exige un protocolo mucho más ordenado que a nivel local, y suele tener 4 fases: Recogida del proceso. Envío de los datos por la red. Selección del proceso. Invocación de la petición Y todo esto x2 para devolver los resultados, claro. Esta comunicación podría realizarse por TCP pero como tiene bajo rendimiento para transferencias breves no sabemos si es lo más adecuado. Los principales problemas que surgen al convertir una llamada local en remota son: Gestión de la memoria y referencias: Todo esto es muy problemático, en especial los apuntadores. Estas referencias a espacios de memoria local que a veces no tienen longitud definida son poco propensos a ser eficientes en invocaciones remotas. Tratamiento de errores: Puede fallar además del cliente, la red o el servidor, y el cliente debe poder reaccionar, reenviando la información si el fallo es temporal o informando del error cuando no se pueda solucionar. El tratamiento de estas situaciones se hace con construcción de excepciones, como en Java o C++. 14 · Arquitectura de sistemas distribuidos Garantías de ejecución: No es lo mismo que la invocación falle a la ida, que falle a la vuelta. Para diferenciarlas se pueden ofrecer garantías de entrega. 5. TIPOS DE PROTOCOLOS RPC RPC: Veamos algunas características muy someras de los distintos protocolos ONC-RPC: Basado en los tipos de datos del lenguaje C, se ha popularizado por su uso en NFS. Corba, DCOM: Desarrollado por la Open Software Foundation y adoptado por Microsoft. RMI (Remote method invocation): Es el mecanismo de invocación remota de Java, y sirve para indicar métodos de otros objetos dentro de la misma o en otra máquina virtual; en este último caso los objetos deben declarar que implementan la interfaz remote y también la excepción java.rmi.remoteException para el tratamiento de excepciones. Es el método más sencillo porque originariamente ya estaba pensado para la invocación remota y es un método muy homogéneo HTTP (Invocación sobre web): Fue concebido como un mecanismo de petición/respuesta en el que se intercambian mensajes y se invocan métodos predefinidos (get, put…). Con la aparición del servidor HTTPD se definió un mecanismo simple CGI (interfaz común de pasarela) para invocar distintos comandos al estilo Unix. SOAP (Simple object access protocol): Es un protocolo para intercambiar en la web datos estructurados y con tipo asociado; puede combinarse con protocolos y formatos como MIME, SMTP y HTTP, para aplicaciones como RPC y mensajería. Arquitectura de sistemas distribuidos · 15 TEMA 5 ARQUITECTURA DE APLICACIONES WEB Tema 5 Arquitectura web de aplicaciones 1. Características de la demanda de páginas web 2. Organización de las aplicaciones en servidores web 3. Servidores Proxy-caché web 4. Contenidos distribuidos Distribución de Zipf Logarítmica y lineal 1. CARACTERÍSTICAS DE LA DEMANDA DE PÁGINAS WEB El tráfico web es el responsable de un buen porcentaje del tráfico en Internet (73%) y no parece que vaya a tender a disminuir; pero lejos de ser un flujo de tráfico constante es muy voluble y cambiante. Un mismo sitio puede recibir muy pocas visitas durante mucho tiempo y, de repente, recibir más peticiones de las que puede servir (tráfico a ráfagas); además dentro de un mismo sitio web, la frecuencia de acceso a documentos sigue la distribución de Zipf, que fija logarítmicamente esta distribución, pero que a grandes rasgos indica que unos pocos documentos copan casi todos los accesos, mientras que la mayoría apenas son visitados; podemos observar en la figura lateral esta distribución de popularidad de Zipf en su formato logarítmico y lineal. Como resumen podemos decir que los distintos estudios del tráfico en web han arrojado las siguientes caracteríticas El tamaño medio de un objeto es de 10-15 Kbytes, aunque también existen documentos de varios Megabytes pero comparativamente son los menos. La mayoría de los accesos a la web son por objetos gráficos. Una página html incluye una media de 10 imágenes y múltiples enlaces a otras páginas. El tráfico web es a ráfagas, por lo que valores medidos con medias durante decenas de segundo son poco fiables. Se cancelan un 5-10% de los accesos web antes de finalizar. Es importante probar el rendimiento de un servidor para comprobar que todo funciona correctamente; así evitaremos la degradación del servicio (responde muy lentamente por exceso de peticiones o tráfico) o situaciones críticas (sobrecargas que hacen que no responda). Para esto la mayoría de los servidores web disponen de herramientas de visualización y archivos log que almacenan todos los sucesos y peticiones que reciben. 2. ORGANIZACIÓN DE LAS APLICACIONES EN SERVIDORES WEB La organización de un servidor web requiere conocer algunos términos: Proceso: La unidad más pesada de la planificación de tareas que ofrece el sistema operativo. No comparte espacios de direcciones ni recursos relacionados con ficheros. Flujo: La unidad más ligera de planificación de tareas que ofrece el sistema operativo. Como mínimo hay un flujo por proceso, y si hay más de uno, comparten la misma memoria y recursos de archivo. Fibra: Flujos gestionados por el usuario con cambios de contexto en operaciones de entrada/salida. Ahora bien, se pueden combinar procesos, flujos y fibras de forma única o múltiple, dependiendo del tipo de servidor web que queramos construir. En general, los modelos con muchos procesos son costosos de memoria y de carga; en servidores de alto rendimiento, los modelos con flujos parecen mejores porque son muy rápidos atendiendo peticiones, aunque son poco portables. En máquinas con un único procesador los modelos con un solo flujo funcionan bien, en máquinas multiprocesador, es necesario usar múltiples flujos o procesos para aprovechar el hardware. En definitiva, como todo depende del hardware que tengamos y del tipo de servidor web que queramos montar, lo mejor es decantarse por un software 16 · Arquitectura de sistemas distribuidos modular, como Apache 2.0 que permite con su módulo de gestión de procesos seleccionar en la instalación el tipo de modelo que queramos ejecutar. Como modelos de organización encontramos: Organización de aplicaciones web CGI – FastCGI - APIs - Servlet Java CGI: Common gateway interface, es la interfaz común de pasarela, un estándar para proporcionar una interfaz web a programas que se ejecutan en cada petición. Cada petición recibe los datos de entrada por la entrada estándar y genera una respuesta por la salida estándar. Es un procedimiento que consume muchos recursos y es lento. FastCGI: Pretendía resolver problemas de velocidad y recursos, principalmente permitiendo que un solo proceso cargado vaya sirviendo peticiones sin descargarse. Los CGI y FastCGI no pueden interactuar con el corazón del servidor (por ejemplo generando logs), para lo que existen alternativas como las APIs de extensión de cada servidor, que son muy prácticas, pero son extensiones no portables (únicas para cada servidor), con complejas de desarrollar y mantener, e introducen riesgo de seguridad en el servidor. Servlet Java: Es una extensión gráfica del servidor que se puede cargar dinámicamente en éste para extender la funcionalidad del servidor web. Son portables, potentes, eficientes, seguras y se integran perfectamente con el ervidor. 3. SERVIDORES PROXY-CACHE WEB Un Proxy es un servidor intermediario que acepta peticiones http de clientes u otros intermediarios y genera a su vez peticiones hacia otros intermediarios o hacia el servidor web destino. Actúa como servidor del cliente y como cliente del servidor. Aprovechando que tanto la petición del cliente como el resultado del servidor pasan por este intermediario, se puede aprovechar para ofrecer algunas funciones: Control de acceso a contenidos: El Proxy consulta que la página solicitada esté permitida por la organización. Control de seguridad: El intermediario genera peticiones que salen a Internet, lo que oculta información y evita ataques directos sobre las máquinas internas de la organización. Adaptar el contenido: Puede también adaptar los objetos que vienen del servidor a las características del cliente: teléfonos móviles, PDA, ajustando el tamaño y peso de los objetos. Aprovechar peticiones reiteradas: y ser usado como Proxy-caché, que es lo que más frecuentemente se hace. El intermediario guarda una copia de los objetos pedidos al servidor, así se puede ahorrar tráfico y peticiones al servidor, sirviéndolas directamente cuando se le vuelvan a pedir. Como esta última función se ha extendido mucho, se define una nueva cabecera en el entorno http para controlar este tipo de peticiones, por ejemplo que un determinado objeto no sea almacenable, definir el tiempo de almacenamiento del objeto (expiración), petición obligatoria del objeto al servidor, etc. Su uso puede producir una reducción del tráfico de la red y en el tiempo de espera del usuario para recibir los contenidos; actualmente los Proxy-caché son objetos pasivos, pero se han propuesto mejorar para hacerlos más activos: acumular documentos de interés en horas de bajo tráfico para tener el contenido preparado en las horas de tráfico pico; traer páginas de Internet que con gran probabilidad un usuario va a consultar a continuación, etc, pero estos futuros Arquitectura de sistemas distribuidos · 17 cambios quizá solo supongan un malgasto de los recursos de comunicación sin llegar a ser realmente efectivos y prácticos. Cuando varios Proxy-caché cooperan se forma una jerarquía, y si están al mismo nivel hablamos de hermanamiento; quizá un Proxy-caché no contenga un documento que se le ha pedido y en lugar de pedirlo al servidor, lo pida a un hermano. El problema es que si un Proxy-caché tiene muchos hermanos, genera tantas peticiones como hermanos tiene y puede suponer una mayor saturación de la red en un intento por ahorrar; un intento de solucionarlo es utilizar los llamados caché-digest, es una tabla hash con la información de qué objetos hay en la memoria de trabajo de cada Proxy y que los hermanos piden periódicamente entre sí para estar actualizados, así cuando tienen una determinada petición, se la hacen al hermano que ya saben que tiene la respuesta. El problema que aparece ahora es que es muy posible que muchos hermanos guarden la misma información, porque ya sabemos que las peticiones siguen la distribución de Zipf. Para solucionarlo a su vez apareció el CARP (Caché array routing protocol), que mediante una función de hash se calcula a qué servidor pedir determinada información, con lo que el contenido no se repite en todos los Proxycaché. CARP tiene problemas cuando aparece o desaparece un servidor Proxycaché ya que debería cambiar el algoritmo de elección y los contenidos que antes se pedían a un servidor determinado, ahora se repartirá entre otros. 4. CONTENIDOS DISTRIBUIDOS Las aplicaciones que ofrecen contenidos en Internet se enfrentan al reto de la escala: un solo servidor ante eventualmente millones de personas que pueden pedirle sus servicios todos a la vez: el proveedor de información debe poner tantos recursos como audiencia pueda tener. Para poder abarcar toda la audiencia, existen diferentes métodos para repartir peticiones entre distintas máquinas: Espejos o mirrors con un programa que redirige la petición http a la mejor réplica. Hacer que el servicio de nombres DNS devuelva diferentes direcciones IP. Redirección en el nivel de transporte: un encaminador mira los paquetes IP de conexiones TCP hacia un servidor web y las redirige a la máquina interna menos cargada. Redirección en el nivel de aplicación: un encaminador mira las conexiones http y puede decidir a qué réplica contactar en función del URL solicitado. Mandar todas las peticiones a un Proxy interno que responda o con contenido previamente guardado en la memoria o que pase la petición a uno o varios servidores internos. Las redes de distribución de contenidos (CDN) son empresas que han instalado máquinas en muchos lugares del mundo y algoritmos para decidir qué máquina es la más adecuada para atender peticiones según la ubicación del cliente y la congestión de la red. Texto elaborado a partir de: Arquitectura de sistemas distribuidos Leandro Navarro Moldes, Joan Manuel Marquès i Puig Junio 2006