Arquitectura de software para sistemas distribuidos
La capacidad de conectar a los usuarios con el recurso computacional por medio de comunicaciones es esencial para las organizaciones, ya que una inversión razonable en hardware y software hace que el acceso a las computadoras esté disponible a todas las personas que lo necesitan.
Sin embargo, hay casos en que el usuario desea procesar datos en una instalación específica y después enviar datos en forma periódica a un sistema de cómputo en la instalación central (a menudo a lugares distintos y separados entre sí); además, los costos de comunicación están aumentando mientras que el de las computadoras decrece (por lo que es común que las empresas utilicen legiones de computadoras pequeñas). Éstas son algunas razones para que los profesionales de la informática tomen en cuenta los “sistemas distribuidos” en sus diseños de sistemas de información.
Un sistema distribuido interconecta los lugares que tienen recursos computacionales para: capturar y almacenar datos, procesarlos y enviar datos e información a otros sistemas, tales como un sistema central.
En general, se podría ver a un sistema distribuido como la unión de una tecnología de red y el uso de potentes máquinas multiprocesadores. Un sistema distribuido es una colección de computadoras independientes o autónomas que aparecen ante los usuarios del sistema como una única computadora.
Los sistemas distribuidos se caracterizan por contar con múltiples elementos de procesamiento y mecanismos de intercomunicación. En estos sistemas existe una independencia a fallos en los nodos de procesamiento, esto debido a que trabajan en un estado de compartición y un esquema de protección en diversas plataformas (heterogéneas).
Utilizar los sistemas distribuidos tiene objetivos como:
– compartir información y otros recursos entre más de un usuario;
– economizar el rendimiento (procesamiento y almacenamiento);
– mantener alta disponibilidad; obtener capacidad de crecimiento incremental y confiabilidad (si un nodo de procesamiento falla, el sistema sigue funcionando).
Una de las ventajas de los sistemas distribuidos, respecto a los centralizados, es la economía, pues es mucho más barato añadir servidores y clientes cuando se requiere aumentar la potencia de procesamiento.
La capacidad de crecimiento incremental se refiere a que se puede añadir procesadores al sistema incrementando su potencia en forma gradual según sus necesidades.
Se dice que tienen una mayor confiabilidad porque al estar distribuida la carga de trabajo en muchas máquinas la falla de una de ellas no afecta a las demás, el sistema sobrevive como un todo.
Además, cuando se opte por una arquitectura distribuida, se deben considerar distintos aspectos, entre otros:
– Escalabilidad
– Performance
– Activación
– Manejo de estados
– Garbage Collection
– Seguridad
Los distintos protocolos que trabajan en sistemas distribuidos cubren algunos de estos aspectos. Los modelos de programación tradicional han sido extendidos para aplicarlos en la programación distribuida.
El llamado a procedimiento convencional local se extendió al remoto (RPC). Al surgir programación orientada a objetos (POO), fue necesaria la invocación remota de métodos (RMI). RMI permite que un objeto que está dentro de un proceso, invoque los métodos de un objeto que está en otro proceso.
El modelo de programación basado en eventos para progresar a la versión distribuida necesitó extender la capacidad de sus objetos de recibir notificaciones de eventos que ocurren en otros objetos a los que quieren acceder.
El uso de interfases para la comunicación entre distintos módulos permite “esconder” implementación y ofrecer solamente una forma de comunicación con el módulo.
La implementación puede cambiar pero la interfase permite que los otros módulos sigan comunicándose con el “modificado” de igual forma, si esto es deseable.
En el modelo RPC, hablamos de interfases de servicio. En el modelo RMI, de interfases remotas.
Las de servicio, usadas en el modelo cliente servidor (C/S), ofrecen la forma de acceder a los servicios que brinda un servidor. La interfaz de servicio es la especificación de los procedimientos que ofrece un servidor; define los argumentos de entrada y salida, etc.
La interfaz remota especifica los métodos de un objeto factibles de ser invocados por objetos de otros procesos. Define argumentos de entrada y de salida.
La diferencia entre ambas interfases es que en la remota, los métodos pueden transmitir objetos como argumentos y como resultados. También se pueden usar referencias de objetos remotos.
Cuando un lenguaje quiere usar RMI, debe considerarse cómo interpretar la definición de las interfases que indiquen cómo invocar los argumentos de entrada y salida. Un ejemplo de esto es Java RMI. Pero esta solución exige que los objetos que se quieren comunicar estén en Java.
Para que objetos implementados en lenguajes diferentes puedan invocarse, existen los lenguajes de definición de interfases (IDL). ORB (Object Request Broker) es el middleware que establece una relación cliente servidor entre objetos. A través del ORB un cliente invoca de forma transparente un método de un objeto servidor ya sea en la misma máquina o a través de la Red.
El ORB provee interoperabilidad entre objetos en ambientes distribuidos. Su tarea comprende:
– interceptar la invocación al objeto; encontrar el objeto invocado;
– transmitir los parámetros; invocar al método; y retornar los resultados.
El cliente no tiene que conocer la ubicación del objeto ni en qué lenguaje está escrito. Sólo necesita saber cómo invocarlo.
En las aplicaciones típicas cliente/servidor el desarrollador tiene dos alternativas: diseñar él mismo un protocolo o usar un estándar que depende del lenguaje, el transporte, etc. En ORB el protocolo es definido por el IDL.
Para poder implementar la reusabilidad, una característica clave de la tecnología de objetos, la capa de middleware es imprescindible para soportar la comunicación entre objetos. Así, la interfase del objeto sirve para especificar los métodos.
Quizás el usuario común, no desarrollador o que no trabaja a partir de datos que ofrecen aplicaciones en la red, no llegue a vislumbrar los cambios o los beneficios, pues la transparencia es uno de los conceptos más importantes de este modelo distribuido.
Pero desde el punto de vista del desarrollador, este modelo le ofrece la posibilidad de: escribir aplicaciones que interactuarán con distintos dispositivos sin tener que modificar su aplicación, permitiendo que su aplicación e-commerce sea accedida sin restricciones de este tipo; reutilizar software escrito por otros desarrolladores; y, lo más importante, reutilizar ese software desinteresándose por cómo y en qué lenguaje está escrito.
Si hablamos de interacción, no podemos obviar que la solución que se presente debe considerar la heterogeneidad antes mencionada. Esta solución debe prever su implementación transparente sobre ambientes multiplataforma.
Analicemos, por ejemplo, el tema de los dispositivos.
La innovación frecuente (consideremos el progreso de la última década en cuanto a teléfonos inalámbricos, teléfonos inteligentes, nuevos modelos de laptops, etc.) exige que el modelo actual tanto de aplicación como de comunicación, no sea suficiente.
Hasta ahora, con cada nuevo dispositivo, era necesaria la adaptación de la aplicación para integrarlo. Las soluciones que se brinden desde el servidor deben tener en cuenta a estos nuevos dispositivos del cliente.
Una alternativa es desarrollar una solución para cada dispositivo, lo cual, obviamente, es ineficiente, considerando que la falta de escalabilidad no permitirá una rápida adaptación de la aplicación a nuevos dispositivos que puedan surgir (y surgirán) en el futuro.
Los dispositivos tienen, por ejemplo, diferentes resoluciones de pantalla. Además, en la mayoría de los casos, deben integrar datos provenientes de diferentes servidores.
El desafío es, entonces, desarrollar una aplicación que deba tener en cuenta esta variedad, y que sea reusable para nuevos dispositivos que surjan (lo cual es lo esperado).
Este objetivo está dentro de lo que se llama ubiquitous connectivity (algo así, como ‘conectividad para todos’, ‘entre todos’). En GLA000 se hace una referencia interesante de los web services como evolución y revolución. Por ejemplo, en un futuro, podemos pensar que una máquina expendedora de gaseosa, wireless, pueda contactar al proveedor para ordenar un pedido sobre una marca de gaseosa faltante. El “diálogo” se establecería entre dispositivos.
Tratando de explotar la ley de Moore y el abaratamiento del ancho de banda, pensar en un modelo distribuido basado en Internet, es hoy una posibilidad cierta.
El implacable progreso de la industria de la computación está mostrado en la Ley de Moore. En 1965, Gordon Moore, el presidente del fabricante de chips Intel, predijo que la potencia de un chip de silicio del mismo precio podría doblarse cada 18 meses durante al menos dos décadas. En la actualidad, su predicción se ha mostrado totalmente acertada.
Este nuevo modelo incluye componentes de software que usan protocolos abiertos de Internet, incluyendo HTTP para transporte y XML para la representación de la información. Es un modelo orientado a servicios WEB. Cualquier dispositivo y plataforma hoy puede trabajar con estos protocolos. De allí que la adaptación al nuevo modelo sea factible a corto plazo.
Y en cuanto a la seguridad, al usar HTTP siempre se puede usar SSL, para obtener un nivel básico, que puede complementarse con servicios de autenticación. Para adaptarse a este modelo, la nueva generación de lenguajes de computadoras debe integrar Internet de una manera transparente.
Las plataformas de lenguajes tipo Java usan interpretadores en el momento de la ejecución para soportar las diferencias en el hardware cliente. Sus características de orientación a objetos no logran la independencia esperada del hardware ni los niveles de performance, ni la interoperabilidad.
La Web ha evolucionado desde contenidos estáticos, como documentos, a contenidos dinámicos, usando servidores de aplicaciones usando business logic, como programas CGI o JAVA y transacciones.
También usan nuevos protocolos como WAP (Wireless Access Control) y WMP (Wireless Markup Language). El popular modelo P2P en una comunicación de igual a igual es utilizado con frecuencia con algunas variaciones; por ejemplo, el modelo cliente-cliente (peer to peer) trata sobre la comunicación entre clientes, sin usar, imprescindiblemente, un servidor.
Como ocurre con los modelos, no es aplicable a todas las situaciones. Si el cliente debe ser autenticado o si los clientes quieren trabajar asincrónicamente, se hace necesario el uso de un servidor. También se debe tener en cuenta la capacidad de proceso del cliente: si no es suficiente, deberá recurrir a otras máquinas para el procesamiento de la información.
Para este modelo se debe garantizar que se cumplen las exigencias de un modelo integrado de distribución sobre Internet, se debe analizar:
– Manejo de identidad y autenticación del usuario y los servicios asociados
– Capacidad de trabajar en línea y fuera de línea
– Optimizar la forma de mostrar la información
– Libre uso de dispositivos
– Interacción con otros usuarios
– Servicios disponibles para el usuario de acuerdo a su personalización
La interfaz de un proceso es la especificación del conjunto de funciones que pueden invocarse sobre él. Esto es válido tanto para C/S como para comunicación entre iguales. En cliente-servidor, cada proceso servidor es una entidad con una interfase definida.
Cuando tratamos con lenguajes OO, un proceso puede encapsular varios objetos. En el modelo OO los nuevos tipos de objetos deben ser instanciados y estar disponibles rápidamente para su invocación.
Cuando el lenguaje lo permite, los procesos distribuidos se organizan como objetos. Se pueden encapsular muchos objetos y las referencias a estos objetos se van pasando a otros procesos para que puedan invocar sus métodos. JAVA, con su RMI (invocación remota de objetos) usa este mecanismo.
Es muy importante en cuanto al diseño, la manera en que se distribuyen las responsabilidades en el modelo distribuido. Esta distribución puede ser estática (por ejemplo, un servidor de archivos se responsabiliza de los archivos no de proxys, mails, o páginas WEB) o más dinámica como es el modelo orientado a objetos donde se pueden instanciar nuevos objetos y nuevos servicios inmediatamente disponibles para ser invocados.
Las referencias a esos procesos deben armarse de tal forma que puedan realizarse invocaciones remotas (o lo que es equivalente, invocaciones a objetos remotos); es decir, invocarse sus métodos desde otros procesos. Cabe aclarar que estas invocaciones deberán ocurrir entre objetos en diferentes procesos sin importar que estén éstos en la misma computadora o en computadoras interconectadas. En consecuencia, a los objetos que pueden recibir invocaciones remotas se les denomina objetos remotos. Por lo contrario, cuando se invocan métodos entre objetos que están en el mismo proceso, son invocaciones locales.
Analizando los objetos remotos comenzaremos por mencionar que para poder invocar un objeto, se debe tener una referencia a él. Y el objeto remoto debe tener una interfaz remota que diga cuál de sus métodos puede invocarse remotamente. Cuando se trabaja con este tipo de objetos, se debe tener en cuenta que, por ejemplo, una vez que el objeto fue borrado, no deben resolverse futuras referencias, ni derivarlas a otros objetos.
En el ambiente C/S se habla de interfaz de servicio pues los servidores proporcionan servicios y para invocarlos debe ofrecer una especificación de los procedimientos disponibles. Define allí también los argumentos de E y de S.
En el modelo de objetos distribuidos, la interfaz remota especifica los métodos de un objeto disponible a ser invocadas por otros procesos. Define también argumentos de entrada y de salida. Pero lo que hay que tener en cuenta, y es lo que lo diferencia del otro modelo, es que los métodos de interfases remotas pueden tener objetos como argumento y como resultado. También se pueden pasar referencias a objetos remotos.
Cuando un proceso cliente quiere invocar un método de un objeto remoto, debe asegurarse de estar invocando el método deseado. El proceso envía un mensaje de invocación al servidor donde está el proceso que alberga el objeto remoto. El mensaje especifica el objeto remoto de una manera que debe ser válida para el sistema distribuido. En un ambiente así, hay distintos procesos que alojan objetos factibles de ser invocados remotamente. La forma de referenciarlos debe asegurar la unicidad.
Una referencia a un objeto remoto es un identificador que es válido dentro del sistema distribuido. Las referencias pueden transmitirse como argumentos y pueden devolverse como resultado de la invocación a métodos remotos. Incluso las referencias pueden compararse para saber si se refieren al mismo objeto. No sólo la referencia debe asegurar la unicidad con respecto a la ubicación: también es importante considerar el tiempo, es decir, la posibilidad de estar invocando una versión que no sea la más reciente. Una forma estática de construir una referencia sería incluir la dirección de Internet de la computadora donde reside, número de puerto del proceso que lo creó y momento de creación y un número de objeto local. Este último número es actualizado cada vez que el proceso crea un nuevo objeto.
El problema es la falta de flexibilidad de este esquema. ¿Qué pasa si los objetos son “reubicados”? ¿Qué pasa con la deseada transparencia de ubicación o de migración? Se puede utilizar un servicio de localización, que utiliza una base de datos que relaciona objetos remotos con sus direcciones actuales, o por lo menos, las últimas direcciones reportadas.
Se llama ‘acción’ a una cadena de invocaciones de métodos relacionados, cada uno de los cuales retornará en algún momento. Se dice que un objeto remoto está activo cuando está disponible para su invocación dentro de un proceso en ejecución. Está en estado pasivo o inactivo, si no está activo en ese momento, pero que se puede llegar a activar. Un objeto pasivo contiene la implementación de sus métodos y su estado.
Cuando un objeto pasivo se “activa”, crea una nueva instancia de su clase y se inicializan las variables de instancia desde el estado que está almacenado. Pueden activarse bajo demanda como cuando son invocados por otros procesos. Los objetos invocados remotamente, cuando no están siendo utilizados pero tienen información, gastan recursos. Por lo tanto, en los servidores hay actividades que se arrancan bajo demanda para activar los procesos.
Por otra parte, serializar un objeto significa “aplanarlo”, es decir, obtener una forma lineal adecuada para ser almacenado en disco o para transmitirlo en un mensaje. La deserialización consiste en volver a llevar esa forma lineal a la forma original del objeto.
El problema de distribuir los procesos a lo largo de la red implica un análisis profundo de cómo se relacionan. Se debe pensar, por ejemplo, en los cambios necesarios y recurrentes en la lógica de negocio (business logic), imposible de realizar rápidamente si las componentes que la implementan están repartidas en varias máquinas pequeñas. Además, los cambios que se realicen en la interfase de usuario no deben incidir en las componentes que implementan la lógica de negocio. Una solución es separar el cliente y la instancia de la componente que se invoca en dos procesos diferentes, donde el proceso cliente trabaja en computadoras orientadas a la interacción con el usuario, y los procesos componentes en computadoras especializadas (y preparadas) para compartir y administrar la lógica de negocio.
Estando en diferentes computadoras, la comunicación entre el proceso cliente y el proceso componente se implementaría de la siguiente forma: en el proceso cliente, se agrega una representación del componente (instance surrogate). En el proceso componente, se crea una representación del cliente (client surrogate).
Las componentes residirán en una computadora prepara para este fin, permitiendo una fácil administración (por ejemplo, en caso de ser necesaria la modificación) y seguridad. Esta arquitectura de distribución es la que usan los sistemas con componentes (CORBA, DCOM/COM/MTS, EJB de Sun).
Una ventaja de la tecnología de componentes es la separación entre lógica de ejecución y lógica de negocio. Pero aún quedaría la duda de ¿cómo asegurar que la componente que responde es realmente la que se invocó? Y, además, ¿cómo asegurar la no-intercepción de la respuesta?
En cuanto al acceso a bases de datos, el modelo distribuido de componentes exige interactuar con múltiples bases, con procesos cooperantes. Las transacciones deben adaptarse a esta nueva forma de trabajo, acostumbrados como están a la relación de requerimiento proceso-base de datos. El sistema de transacciones tradicional trabaja adecuadamente en ambientes “cerrados”, con transacción de corta vida. En el nuevo modelo a plantear, la lógica de negocio distribuida es implementada con lenguajes como el BPEL4WS.
Con respecto a la escalabilidad, en el modelo distribuido de componentes, cada cliente es representado en el proceso cliente por el surrogate y la instancia de la componente. Esas instancias seguramente se conectarán con distintas bases generando varios mensajes, y además, procesarán gran cantidad de datos. Si cada PC es un cliente potencial, estaremos generando una actividad que no se puede sostener. Hay que lograr una escalabilidad que permita un aumento importante en el número de clientes. Para Roger Sessions algunas soluciones las da TPM, Transaction Processing Monitors, de Microsoft.
Haciendo referencia a una de las aplicaciones de estos modelos, las aplicaciones Three-Tier tienen importantes ventajas:
– Separación entre la interfase de usuario y la lógica de negocio.
La interfase de usuario se ubica en máquinas a tal efecto, diferentes de las máquinas donde reside la lógica de negocio. Física y lógicamente están separadas.
Esta característica brinda flexibilidad tanto para el diseño de la interfase, como para la reusabilidad de la lógica de negocio. Por ejemplo, una componente que calcula el precio de un producto de acuerdo a diferentes pautas, puede ser accedida por páginas Web, PCs clientes de negocios mayoristas, servicios autorizados, etc.
– Rapidez en el desarrollo y actualización
Si la lógica de negocio ha sido implementada y probada exitosamente, podrán agregarse nuevas interfases rápidamente. También modificar las componentes, sin modificar la interfase de usuario. O construir componentes nuevas e incluirlas posteriormente, una vez que se hayan probado.
– Facilidad de administración
Otro aspecto importante en las estructuras distribuidas son los lenguajes de definición de interfases (IDL), los cuales fueron desarrollados para que los objetos en lenguajes diferentes puedan invocarse entre sí. Corba usa CORBA IDL, Sun propone XDR para su RPC, DCE usa su IDL para RPC, Microsoft usa DCOM IDL.
Un punto interesante es si estos IDLs exponen las interfases de manera tal que sean comprendidos por cualquier objeto invocante.
En estos lenguajes, se denomina “representación externa de datos” al estándar que acuerdan dos o más computadoras para intercambiar datos. De esta forma se superan problemas como el ordenamiento de enteros, diferentes formas de representar flotantes o la cantidad de caracteres que toman los distintos formatos.
En RMI o RPC se debe llevar cualquier estructura que desea pasarse como argumento o devuelto como resultado a una forma plana, que viaje y sea interpretada correctamente en el destino (serialización de objetos).
Por lo anteriormente expuesto podemos concluir que el modelo distribuido sobre la Red es hoy una necesidad. Pero para implementar ese modelo distribuido es imprescindible acordar cómo trabajar con distinto hardware, distintas plataformas; integrando servicios, pero sin perder la transparencia para el usuario.
Fuente: Informática I de la facultad de contaduría y administración, UNAM.