0% encontró este documento útil (0 votos)
375 vistas91 páginas

Justificación Y Resumen

Este documento describe los conceptos fundamentales de la arquitectura de sistemas distribuidos. Explica que la arquitectura se refiere a la estructura de un sistema y cómo se organizan y comunican sus componentes. Una buena arquitectura influye en aspectos como el rendimiento, escalabilidad y eficiencia del sistema. El documento también discute la separación de preocupaciones entre componentes y cómo esto afecta a la facilidad de implementación y mantenimiento del sistema. Finalmente, hace la distinción entre aplicaciones de red y aplicaciones distribuidas.

Cargado por

Johao Villarroel
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
375 vistas91 páginas

Justificación Y Resumen

Este documento describe los conceptos fundamentales de la arquitectura de sistemas distribuidos. Explica que la arquitectura se refiere a la estructura de un sistema y cómo se organizan y comunican sus componentes. Una buena arquitectura influye en aspectos como el rendimiento, escalabilidad y eficiencia del sistema. El documento también discute la separación de preocupaciones entre componentes y cómo esto afecta a la facilidad de implementación y mantenimiento del sistema. Finalmente, hace la distinción entre aplicaciones de red y aplicaciones distribuidas.

Cargado por

Johao Villarroel
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

5.

2 LA VISTA DE ARQUITECTURA 279

5.20 Ejercicios de fin de capítulo ........................................... .................................................. ................. 376


5.20.1 Preguntas .............................................. .................................................. ............ 376
5.20.2 Ejercicios de programación ............................................. ........................................... 377
5.20.3 Respuestas a las preguntas al final del capítulo ....................................... .............................. 378
5.20.4 Lista de actividades en el texto ......................................... ............................................... 380
5.20.5 Lista de recursos complementarios ........................................... ................................. 381

5.1 JUSTIFICACIÓN Y RESUMEN


Un sistema distribuido por definición comprende al menos dos componentes, pero algunos sistemas comprenden
muchos componentes y exhiben un comportamiento muy complejo como resultado. La arquitectura describe la
forma en que se estructuran los sistemas y cómo se interconectan los componentes constituyentes y las relaciones
entre los componentes; esto incluye la organización de canales de comunicación y control entre pares o grupos de
componentes. La elección de la arquitectura para un sistema determinado tendrá un impacto en su escalabilidad,
solidez y rendimiento, así como en la eficiencia con la que se utilizan los recursos del sistema; de hecho,
potencialmente impacta todos los aspectos de la efectividad del sistema.
Hay muchas razones por las que los sistemas están diseñados como una serie de componentes, algunos
relacionados con la funcionalidad, algunos relacionados con el acceso a los recursos y algunos relacionados con la
escala de los sistemas, entre otros. Se discuten las razones por las que los sistemas se construyen como una
colección de componentes, y también la amplia variedad de arquitecturas de sistemas que surgen como resultado.
Hay una serie de estructuras y patrones que ocurren comúnmente y también muchas estructuras específicas de la
aplicación. Además, algunas estructuras son estáticas, es decir, la conectividad entre componentes se decide en
tiempo de diseño, mientras que otros sistemas tienen estructuras dinámicas y conectividad, lo cual surge debido al
contexto operativo y al estado del propio sistema más amplio en el que se ejecuta la aplicación. . Se exploran los
mecanismos para respaldar el descubrimiento de componentes dinámicos y la conectividad,

Se examinan los efectos de la heterogeneidad en los sistemas, así como las formas en que se puede superar el
desafío de la heterogeneidad con servicios como middleware y técnicas como la virtualización de hardware. La
estructura a nivel de componente se examina con la ayuda de ejemplos prácticos de refactorización y la creación de
una biblioteca de software. El uso de la replicación como técnica de diseño arquitectónico para cumplir con los
requisitos no funcionales, incluida la solidez, la disponibilidad y la capacidad de respuesta, se explora en una amplia
actividad práctica.

5.2 LA VISTA DE ARQUITECTURA


La arquitectura de un sistema es su estructura. Las aplicaciones distribuidas comprenden varios componentes que
tienen relaciones de comunicación y relaciones de control con otros componentes. Estos componentes pueden
organizarse en una estructura jerárquica donde los componentes ocupan diferentes capas según su función.

Quizás, la mayor influencia en la calidad y eficacia generales de una aplicación distribuida es


su arquitectura. La forma en que una aplicación se divide en componentes y la forma
280 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Estos componentes se organizan posteriormente en una estructura adecuada, el apoyo a la comunicación y el


control tiene un impacto muy fuerte en el rendimiento alcanzado. Las características de rendimiento influenciadas
por la arquitectura incluyen escalabilidad (por ejemplo, en términos de la forma en que el rendimiento se ve
afectado por aumentos en el número de componentes en el sistema o por aumentos en el rendimiento medido
como el número de transacciones por unidad de tiempo), flexibilidad (por ejemplo, , en términos del acoplamiento
entre componentes y el grado en que es posible la (re) configuración dinámica), y eficiencia (por ejemplo, en
términos de la intensidad de comunicación entre componentes medida por el número de mensajes enviados y la
sobrecarga total de comunicación incurrida).
Existe una diferencia importante entre una arquitectura física y una arquitectura lógica. La arquitectura
física describe la configuración de las computadoras y su interconectividad. Los desarrolladores de
aplicaciones y sistemas distribuidos se preocupan principalmente por la arquitectura lógica en la que la
conectividad lógica de los componentes es importante, pero la ubicación física de estos componentes (es
decir, su asignación a las computadoras reales) no es una preocupación. La lógica de la aplicación se
considera distribuida incluso si todos los procesos que realizan el trabajo residen en el mismo equipo físico.
Es común que los procesos se distribuyan entre varios equipos, y esto introduce no solo varias
consideraciones especiales, más obviamente el aspecto de la comunicación, sino también problemas de
sincronización y tiempo.

5.2.1 SEPARACIÓN DE INTERESES


Una aplicación se define y se distingue por su funcionalidad, es decir, lo que realmente hace. Para lograr esta
funcionalidad, hay una serie de preocupaciones diferentes en el nivel de la lógica empresarial. Estas inquietudes
pueden incluir aspectos específicos de la funcionalidad, el cumplimiento de requisitos no funcionales como la
robustez o la escalabilidad, así como otros problemas como la accesibilidad y la seguridad. Estos diversos requisitos
y comportamientos se asignan a los componentes reales de formas que dependen en gran medida de la aplicación,
teniendo en cuenta no solo las funcionalidades en sí, sino la priorización específica entre las funcionalidades que
depende de la aplicación.
Debería ser posible identificar los componentes de software específicos que proporcionan una funcionalidad
particular. Esto se debe a que un requisito funcional es algo que el sistema realmente debe hacer, o realizar, y por lo
tanto, por lo general, puede expresarse explícitamente en la documentación de diseño y, finalmente, traducirse en
código. Por ejemplo, el cifrado de un mensaje antes de enviarlo se puede realizar en una función de código llamada EncryptMessage
(), que está contenido dentro de un componente específico de la aplicación. Sin embargo, generalmente no es
posible implementar requisitos no funcionales directamente en el código (por implicación de su naturaleza "no
funcional"). Tome un par de requisitos muy comunes, como escalabilidad y eficiencia; Casi todas las aplicaciones
distribuidas las tienen entre sus requisitos no funcionales, pero incluso los desarrolladores de software más
experimentados no podrán escribir funciones.
Escalabilidad () o Eficiencia() para proporcionar estas características. Esto se debe a que la escalabilidad y la
eficiencia son no funciones como tales son cualidades. En lugar de proporcionar una función claramente delimitada,
toda la aplicación (o ciertas partes clave de ella) debe diseñarse para garantizar que la estructura y el
comportamiento generales resultantes sean escalables y eficientes. Sin embargo, puede haber funciones que
contribuyan directa o indirectamente al logro de requisitos no funcionales. Por ejemplo, un método como CompressMessageBeforeSend
() puede contribuir tanto a la escalabilidad como a la eficiencia. Sin embargo, el logro de escalabilidad y eficiencia
depende adicionalmente de la estructura de nivel superior, como
5.2 LA VISTA DE ARQUITECTURA 281

como la forma en que los componentes se acoplan entre sí, así como aspectos específicos de la
conducta.
Uno de los pasos clave para definir la arquitectura de una aplicación es la separación de las
preocupaciones, es decir, decidir cómo dividir la lógica de la aplicación para que se pueda distribuir
entre los distintos componentes. Esto debe hacerse con mucho cuidado. Las arquitecturas en las que
la separación funcional de la lógica empresarial entre los componentes es bastante clara con límites
bien definidos tienden a ser más fáciles de implementar y son potencialmente más escalables. Las
situaciones en las que hay muchos componentes pero la funcionalidad no está claramente dividida
entre ellos tienen más probabilidades de sufrir problemas de rendimiento o eficiencia (debido a
requisitos de comunicación adicionales) y también es probable que sean menos robustas debido a las
complejas dependencias entre los componentes y las actualizaciones continuas a través del ciclo de
vida del sistema;
A menudo, los servicios como los servicios de nombres y los servicios de intermediarios se emplean específicamente para
desacoplar componentes para garantizar que los componentes en sí mismos sigan siendo lo más simples e independientes posible;
esto promueve la flexibilidad en términos de configuración en tiempo de ejecución y la agilidad en términos de mantenimiento y
actualización de por vida.

5.2.2 REDES Y DISTRIBUCIÓN


No todas las aplicaciones que utilizan la red para comunicarse se clasifican como aplicaciones distribuidas.
Una aplicación de red es aquella en la que la red transmite mensajes entre componentes, pero donde la lógica
de la aplicación no se extiende a través de los componentes, por ejemplo, situaciones en las que uno de los
componentes es simplemente una interfaz de usuario como con un emulador de terminal, como un cliente Telnet. .
El usuario ejecuta una aplicación local que proporciona una interfaz a otra computadora para que los comandos se
puedan ejecutar de forma remota y los resultados se presenten en la pantalla del usuario. La aplicación del usuario
en este caso es solo un portal de acceso o interfaz que permite al usuario ejecutar comandos en la computadora
remota. En realidad, no contiene ninguna lógica de aplicación; más bien, se conecta a la computadora remota y
envía y recibe mensajes de formas predefinidas. Las aplicaciones que se utilizan permanecen remotas para el
usuario.
En una aplicación de red, los dos o más componentes suelen ser visibles explícitamente para los usuarios; por ejemplo,
es posible que tengan que identificar cada componente y conectarse a ellos (como en el ejemplo de Telnet anterior, donde
el usuario sabe que está iniciando sesión en un sitio remoto). Un ejemplo adicional es cuando se utiliza un navegador web
para conectarse a una página web específica, el usuario es consciente de que el recurso al que se accede es remoto
(normalmente, el usuario ha proporcionado explícitamente la URL de la página web o ha hecho clic en un hipervínculo).

A diferencia de las aplicaciones de red, los términos "aplicación distribuida" y "sistema distribuido" implican que
la lógica y la estructura de una aplicación se distribuyen de alguna manera en múltiples componentes, idealmente
de tal manera que los usuarios de la aplicación no conocen la distribución en sí. .
La principal diferencia es, por tanto, la transparencia (además de la diferenciación en cuanto a si la lógica
empresarial está distribuida); El objetivo de un buen diseño de sistemas distribuidos es crear la ilusión de una sola
entidad y ocultar la separación de componentes y los límites entre las computadoras físicas. El grado de
transparencia es una métrica principal para medir la calidad de una aplicación o sistema distribuido. Este tema se
analiza con más detalle más adelante en este capítulo.
282 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

5.2.3 COMPLEJIDAD EN SISTEMAS DISTRIBUIDOS


La gestión de la complejidad es una preocupación principal en el diseño y desarrollo de aplicaciones y sistemas
distribuidos. Los sistemas pueden ser muy complejos en términos de su estructura, su funcionalidad y / o su
comportamiento.
Existe una amplia variedad de fuentes de complejidad; las categorías comunes incluyen las siguientes:

• El tamaño total del sistema. Esto incluye la cantidad de computadoras, la cantidad de componentes de
software, la cantidad de datos y la cantidad de usuarios.
• El alcance de la funcionalidad. Esto incluye la complejidad de funciones específicas y también la
variedad y amplitud de funcionalidad en todo el sistema.
• El alcance de la interacción. Esto incluye la interacción entre diferentes características / funciones, así como la
comunicación entre los componentes del software, la naturaleza y el alcance de la comunicación entre los
usuarios y el sistema, y posiblemente la interacción indirecta entre los usuarios como resultado del uso del
sistema (por ejemplo, en aplicaciones como la banca). con cuentas y juegos compartidos).

• La velocidad a la que opera el sistema. Esto incluye la velocidad a la que llegan las solicitudes de los usuarios
al sistema, el rendimiento del sistema en términos de la cantidad de transacciones completadas en un
período de tiempo determinado y la cantidad de comunicación interna que se produce al procesar las
transacciones.
• Simultaneidad. Esto incluye a los usuarios que envían solicitudes de servicio al mismo tiempo y también los efectos que surgen
de tener muchos componentes de software y también muchos elementos de procesamiento que operan en paralelo dentro de la
mayoría de los sistemas.
• Reconfiguraciones. Esto incluye la reconfiguración forzada causada por fallas de varios componentes, así
como la reconfiguración intencionada (automática o manual) para actualizar la funcionalidad o mejorar la
eficiencia.
• Condiciones externas o ambientales. Esta amplia categoría de factores incluye fallas de energía que afectan a
las computadoras host y los niveles de carga dinámica en la red de comunicación.

De esta lista, es evidente que hay muchas causas de complejidad. Un cierto nivel de complejidad es
inevitable para lograr la riqueza de comportamiento necesaria para que las aplicaciones cumplan con sus
objetivos de diseño. No es posible eliminar por completo la complejidad.
La complejidad es indeseable porque dificulta la comprensión de todos los aspectos de los sistemas y sus posibles
comportamientos por completo y, por lo tanto, es más probable que las debilidades en términos de diseño o configuración
deficientes puedan ocurrir en sistemas más complejos. Muchos sistemas son tan complejos que ninguna persona individual
puede comprender todo el sistema. Con tales sistemas, es muy difícil predecir un comportamiento específico en ciertas
circunstancias o identificar las causas de fallas o ineficiencias, y también requiere mucho tiempo configurar estos sistemas
para un comportamiento óptimo, incluso si es posible en un marco de tiempo realista.
Dado que no es posible eliminar la complejidad de las aplicaciones distribuidas, la mejor práctica es reducir la
complejidad cuando surgen oportunidades y evitar la introducción de una complejidad innecesaria. Esto requiere
que los diseñadores consideren las opciones disponibles con mucho cuidado y hagan un esfuerzo especial para
comprender las consecuencias de las diversas estrategias y mecanismos que emplean. La arquitectura de un
sistema tiene potencialmente un gran impacto en su complejidad general porque describe la forma en que los
componentes están conectados entre sí y la forma en que se produce la comunicación y el control entre estos
componentes.
5.2 LA VISTA DE ARQUITECTURA 283

5.2.4 ARQUITECTURAS EN CAPAS


Una arquitectura plana es donde todos los componentes operan al mismo nivel; no hay coordinación o control
central; en cambio, estos sistemas pueden describirse como colaborativos o autoorganizados. Tales arquitecturas se
dan en algunos sistemas naturales en los que un gran número de organizaciones muy simples como insectos o
células en sustancias como moldes interactúan para lograr estructuras y / o comportamientos más allá de los
capaces de un elemento individual. Este concepto se llama emergencia y se ha utilizado eficazmente en algunos
sistemas de software, como los sistemas basados en agentes.
Sin embargo, tales enfoques se basan en características del sistema que incluyen tener un gran número de
entidades similares, así como interacciones que ocurren aleatoriamente solo entre entidades vecinas, y estos
sistemas tienden a funcionar mejor cuando las entidades mismas son simples en términos del conocimiento que
poseen y las funciones. ellos realizan. La escalabilidad es un desafío serio cuando la comunicación entre
componentes se extiende más allá de los vecinos inmediatos o cuando las interacciones ocurren a una velocidad tal
que excede el ancho de banda de comunicación disponible.
La mayoría de los sistemas de computación distribuida contienen un número mucho menor de componentes que los
que se encuentran en los sistemas emergentes (aunque todavía puede haber un gran número de miles). Sin embargo, los
distintos componentes no suelen ser idénticos en todo el sistema. Puede haber grupos de componentes idénticos, como
cuando un servicio particular comprende una serie de componentes de servidor de réplica para lograr robustez y / o
rendimiento, pero dichos grupos serán subsistemas y engranajes de manera efectiva en una máquina más grande. Los
requisitos de comunicación y control entre componentes de sistemas distribuidos no suelen ser uniformes; Es probable que
algunos componentes coordinen o controlen el funcionamiento de otros y también que algunos componentes interactúen
intensamente con otros componentes específicos y mucho menos, o nada en absoluto con otros.
Las arquitecturas de software en capas comprenden múltiples capas de componentes que se colocan en agrupaciones
lógicas según el tipo de funcionalidad que proporcionan o según sus interacciones con otros componentes, de modo que la
comunicación entre capas se produce entre capas adyacentes. Las aplicaciones y sus subcomponentes que interactúan
directamente con los usuarios ocupan la capa superior de la arquitectura, los servicios están más abajo, el sistema operativo
viene a continuación, mientras que los componentes como los controladores de dispositivos que interactúan con el
hardware del sistema se encuentran en las capas inferiores de la arquitectura. . Las capas también se pueden utilizar para
organizar los componentes dentro de una aplicación o servicio específico; ver Figura 5.1 .

Cliente

Aplicaciones de usuario Coordinador de Servicios

Servicio replicado
Servicios genéricos
(instancias de servidor)

Sistema operativo

Controladores de dispositivo

Hardware

Capas a nivel de sistema


(a) (B) Capas dentro de una aplicación específica

FIGURA 5.1

Generalización del uso de capas para dotar de estructura.


284 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Figura 5.1 ilustra de manera generalizada cómo los sistemas pueden organizarse en capas para proporcionar estructura y así gestionar la

complejidad. Los sistemas modernos son demasiado complejos para que los usuarios puedan entenderlos en su totalidad y, por lo tanto, es

difícil y engorroso tomar decisiones de configuración en toda la gama de funciones para utilizar el sistema. La separación en capas limita el

alcance de cada capa y permite que se produzca la configuración relevante mientras se abstraen los detalles que preocupan a otras capas. La

parte (a) de la figura muestra cómo se pueden usar las capas para separar las preocupaciones de las aplicaciones de las del software y hardware

de los sistemas. Para poner esto en contexto, cuando se usa una aplicación en particular, el usuario solo debería tener que interactuar con la

aplicación en sí. No es deseable desde el punto de vista de la usabilidad que el usuario tenga que configurar los servicios de soporte o realizar

ajustes en la configuración operativa para poder utilizar la aplicación. Un ejemplo sencillo de esto en la práctica es el uso de una aplicación de

procesamiento de texto para escribir este párrafo. La aplicación es una de las muchas en mi computadora que pueden usar el teclado. La

aplicación indica al sistema operativo que requiere entrada desde el teclado y el sistema operativo realiza el mapeo del flujo de entrada desde el

controlador del dispositivo del teclado al proceso de procesamiento de texto sin que el usuario tenga que involucrarse o incluso ser consciente

de que esto está ocurriendo. El sistema operativo asigna automáticamente el dispositivo de teclado a otros procesos si el usuario cambia entre

diferentes aplicaciones (por ejemplo, una vez que llego al final de este párrafo, Podría revisar mi correo electrónico antes de continuar con el

libro). También está el problema de las actualizaciones de hardware; si reemplazo mi teclado por uno diferente (quizás uno con teclas de función

adicionales o una bola de rodillo integrada), es probable que se necesite un nuevo controlador de dispositivo para el nuevo teclado. No quiero

tener que reconfigurar mi aplicación de procesamiento de texto para acomodar el nuevo teclado; el sistema operativo debe reasignar el flujo de

entrada de mi proceso de aplicación al nuevo controlador de dispositivo de una manera que sea transparente para el proceso en sí y, por lo

tanto, para el usuario. No quiero tener que reconfigurar mi aplicación de procesamiento de texto para acomodar el nuevo teclado; el sistema

operativo debe reasignar el flujo de entrada de mi proceso de aplicación al nuevo controlador de dispositivo de una manera que sea

transparente para el proceso en sí y, por lo tanto, para el usuario. No quiero tener que reconfigurar mi aplicación de procesamiento de texto

para acomodar el nuevo teclado; el sistema operativo debe reasignar el flujo de entrada de mi proceso de aplicación al nuevo controlador de

dispositivo de una manera que sea transparente para el proceso en sí y, por lo tanto, para el usuario.

La parte (b) de la figura ilustra cómo las aplicaciones pueden estructurarse internamente en varias capas (esta
capacidad de subdividir también se aplica a las otras partes del sistema que se muestran en la parte (a)). Se muestra
un ejemplo importante en el que una aplicación se divide en varios componentes, de los cuales el usuario solo está
expuesto a la parte del cliente (por lo tanto, se muestra como el componente superior; conceptualmente, el usuario
mira hacia abajo desde arriba). Este tema se explora en detalle en Sección 5.5
de este capítulo.
El uso beneficioso de las capas en las pilas de protocolos de red se ha discutido en el Capítulo 3 y proporciona una
justificación adicional del valor de las estructuras en capas para garantizar la mantenibilidad y la capacidad de
administración de sistemas complejos con una rica funcionalidad.
Las arquitecturas en capas son muy populares para los sistemas distribuidos. Las razones de esto incluyen las
siguientes:

• Dentro de un sistema distribuido, puede haber muchas aplicaciones distribuidas. Cada una de estas aplicaciones puede
compartir algunos servicios; Un buen ejemplo de esto es un servicio de autenticación que, por lo tanto, garantiza que
usuarios específicos tengan derechos de acceso consistentes a los servicios en todo el sistema y, por lo tanto, es
menos probable que la seguridad del sistema sufra las debilidades que surgirían si algunos puntos de entrada están
menos protegidos. que otros. Puede ser útil separar lógicamente las aplicaciones finales distribuidas (las que brindan
servicio a los usuarios), de las aplicaciones de servicio (que pueden estar distribuidas en sí mismas pero brindan
servicios a otras aplicaciones en lugar de directamente a los usuarios).

Figura 5.2 ilustra la situación en la que múltiples aplicaciones finales interactúan con múltiples servicios; el uso
de capas mantiene la estructura.
5.2 LA VISTA DE ARQUITECTURA 285

Aplicación de usuario n. ° 1 Aplicación de usuario n. ° 2

Servicio genérico #A Servicio genérico #B


(por ejemplo, autenticación) (p. ej., base de datos)

FIGURA 5.2

Las capas facilitan la separación lógica de tipos de componentes y proporcionan una estructura para la interacción entre los
componentes de los sistemas.

• Además de las aplicaciones y servicios distribuidos, existe el software del sistema que incluye sistemas
operativos y varios componentes especializados, como controladores de dispositivos. El software del sistema
en sí puede ser muy complejo en términos de la cantidad de componentes que comprende y la gama de
funcionalidades que proporciona.
• Las capas proporcionan una estructura en la que los componentes ocupan la misma capa que los
componentes similares; sentarse en capas más altas que los componentes que controlan o coordinan o utilizan
los servicios de; y sentarse debajo de los componentes que los coordinan o a los que dan servicio. Existe un
• acoplamiento natural entre capas adyacentes. También hay un desacoplamiento de capas no adyacentes que
contribuye a la flexibilidad y adaptabilidad; esto fomenta una división clara de roles y funcionalidad entre
categorías de componentes y también fomenta el uso de interfaces estandarizadas y bien documentadas entre
componentes (especialmente en los límites entre capas).

5.2.5 ARQUITECTURAS JERÁRQUICAS


Una arquitectura jerárquica comprende múltiples niveles de componentes conectados de tal manera que
reflejan las relaciones de control y comunicación entre ellos. El nodo superior en una relación particular se
denomina padre, mientras que el nodo inferior de la relación se denomina hijo. Un nodo que no tiene nodos
debajo de él se denomina nodo hoja. La organización jerárquica tiene el potencial de lograr escalabilidad,
control, configuración y estructura simultáneamente.
La jerarquía ilustra la importancia relativa de los componentes, los que están más arriba en la estructura suelen
tener roles más centrales o clave. Esto se relaciona con la forma en que la mayoría de las empresas están
organizadas, con los gerentes centrales superiores en la estructura, luego los líderes de departamento, mientras
que los trabajadores con áreas de responsabilidad (funcionalidad) muy específicas y bien definidas ocupan los
nodos hoja. En las empresas organizadas jerárquicamente, la comunicación normal es entre los trabajadores y su
gerente (que está en el siguiente nivel en la estructura). Si algo tiene que pasar a un nivel superior, normalmente se
retransmite a través de los administradores de cada nivel y no se pasa directamente entre capas no adyacentes.
Esto tiene el efecto de mantener un régimen de comunicación y control claro que es apropiado para muchas
organizaciones grandes que de otra manera tendrían problemas con problemas de escalabilidad (por ejemplo,
imagine la complejidad y confusión que podría resultar si todos los trabajadores de una gran empresa contactaran
a la alta dirección en un diariamente). Otro ejemplo del uso de la jerarquía es la organización de grandes grupos de
personas, como ejércitos, fuerzas policiales y gobiernos. En tales casos, es importante
286 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

tienen una toma de decisiones centralizada para las estrategias de más alto nivel, mientras que las decisiones más localizadas se
toman más abajo en la estructura. Es de esperar que el resultado sea un equilibrio entre un sistema uniforme administrado
centralmente con respecto a las principales políticas, al tiempo que permite la autonomía local para asuntos que no necesitan la
atención de la alta dirección.
Sin embargo, las estructuras jerárquicas rígidas pueden ir en contra de la flexibilidad y el dinamismo; por ejemplo, la necesidad
de pasar mensajes a través de varias capas provoca gastos generales y retrasos. Las reorganizaciones pueden ser prohibitivamente
complejas, especialmente cuando los componentes están muy interconectados.
Figura 5.3 ilustra variaciones comunes de estructuras jerárquicas. Los árboles anchos (o planos) se caracterizan por
tener pocos niveles y una gran cantidad de componentes conectados al mismo nivel a un solo nodo padre; esto puede
afectar la escalabilidad porque el nodo principal debe administrar y comunicarse con cada uno de los nodos secundarios.
Los árboles profundos tienen muchas capas con relativamente pocos nodos en cada capa. Esto puede ser útil cuando se
justifica una separación funcional tan detallada, pero en general, las capas adicionales son problemáticas porque añaden
complejidad. Los principales problemas específicos son los aumentos en los costos de comunicación y la latencia de la
comunicación y el control, ya que, en promedio, los mensajes deben transmitirse hacia arriba y hacia abajo en más niveles
del árbol. En general, un árbol equilibrado (es decir, se logra un equilibrio entre la anchura y la profundidad del árbol) es casi
óptimo en términos del compromiso entre longitudes de ruta promedio cortas para la comunicación y también la necesidad
de limitar el número de subordinados en cualquier punto del árbol para la manejabilidad. Un árbol binario es un caso
especial en el que cada nodo tiene (como máximo)

(a) Árbol ancho (B) Árbol profundo

(C) Árbol equilibrado (D) Árbol binario

FIGURA 5.3

Estructuras jerárquicas.
5.3 HETEROGENEIDAD 287

dos subordinados. Es más probable que se encuentren dentro de las estructuras de datos que en las arquitecturas de los
componentes del sistema, pero se incluyen aquí para completarlos.

5.3 HETEROGENEIDAD
Los sistemas homogéneos son aquellos en los que todas las computadoras son iguales, en términos de su hardware y
configuración, recursos y sistema operativo. Estos sistemas existen cuando, por ejemplo, una empresa o universidad equipa
una oficina o un laboratorio con computadoras idénticas o cuando se implementa un sistema de sensores a medida con
nodos de sensores idénticos. Sin embargo, en el caso general, los sistemas de procesamiento no son idénticos y las diversas
diferencias entre ellos pueden afectar el esfuerzo de configuración y administración y pueden causar problemas de
interoperabilidad, de diversa complejidad.
La heterogeneidad es un concepto muy importante para los sistemas distribuidos, tanto en términos de una característica
arquitectónica intencionada para lograr un determinado rendimiento o comportamiento, como en términos de que es uno de los
principales desafíos para la interoperabilidad y la portabilidad del código.

5.3.1 DEFINICIONES Y FUENTES DE HETEROGENEIDAD


Hay tres causas principales de heterogeneidad, que son tecnológicas, intencionales y accidentales. Los avances tecnológicos conducen a nuevas

plataformas o actualizaciones con mejores recursos de plataformas anteriores. Otros factores tecnológicos incluyen avances en sistemas

operativos y lenguajes de programación, así como la introducción ocasional de nuevos protocolos de red. La heterogeneidad a menudo se

introduce intencionalmente a través del diseño o la configuración. Por ejemplo, cuando se utilizan plataformas más potentes para alojar

servicios, mientras que los usuarios tienen estaciones de trabajo menos potentes para acceder a los servicios. Un segundo ejemplo es donde se

elige un sistema operativo como Microsoft Windows para la estación de trabajo de acceso debido a la popular interfaz de usuario que

proporciona, mientras que Unix se elige para las plataformas de alojamiento de servicios debido a que tiene una mejor capacidad de

configuración. Un tercer ejemplo es cuando un servicio se aloja en una computadora estática convencional, mientras que los dispositivos de

computación móvil, con plataformas y niveles de recursos completamente diferentes, se utilizan para acceder al servicio. La heterogeneidad se

introduce accidentalmente, por ejemplo, cuando hay actualizaciones por etapas en los sistemas de hardware o cuando se mejoran las máquinas

individuales o cuando se instalan diferentes versiones del mismo sistema operativo base en diferentes computadoras. Incluso una actualización

en línea automatizada del sistema operativo que se produce en una computadora, pero no en otra, introduce potencialmente heterogeneidad si

el comportamiento de uno cambia de una manera que no cambia el comportamiento del otro. La heterogeneidad se introduce accidentalmente,

por ejemplo, cuando hay actualizaciones por etapas en los sistemas de hardware o cuando se mejoran las máquinas individuales o cuando se

instalan diferentes versiones del mismo sistema operativo base en diferentes computadoras. Incluso una actualización en línea automatizada del sistema operativo qu

Hay tres categorías principales de heterogeneidad: rendimiento, plataforma y sistema operativo. La


heterogeneidad del rendimiento surge de las diferencias en la provisión de recursos que conducen a un
rendimiento diferente de las unidades informáticas. Las características comunes de los recursos que
conducen a la heterogeneidad del rendimiento incluyen el tamaño de la memoria, la velocidad de acceso a
la memoria, el tamaño del disco, la velocidad de acceso al disco, la velocidad del procesador y el ancho de
banda de la red en la interfaz de red de acceso a la computadora. En general, es poco probable que dos
computadoras tengan una configuración de recursos idéntica y, por lo tanto, generalmente habrá algún
elemento de rendimiento diferente. Hay muchas formas en las que surge la heterogeneidad del
rendimiento a través de la adquisición, actualización y configuración normales del sistema de servicios
alojados, como los sistemas de archivos.
288 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

La heterogeneidad de la plataforma (también denominada heterogeneidad de la arquitectura) surge de las diferencias en la plataforma

subyacente, las instalaciones de hardware, el conjunto de instrucciones, el orden de bytes de almacenamiento y transmisión, el número de

procesadores reales dentro del núcleo de cada máquina, etc.

La heterogeneidad del sistema operativo surge de las diferencias que ocurren entre diferentes sistemas
operativos o diferentes versiones de sistemas operativos. Estos incluyen diferencias en la interfaz de
proceso, diferentes tipos de provisión de subprocesos, diferentes niveles de seguridad, diferentes servicios
ofrecidos y la medida en que las interfaces son estándar o abiertas (publicadas) versus diseños propietarios.
Estas diferencias afectan la compatibilidad y los desafíos relacionados con la migración del software entre los
sistemas.

5.3.2 HETEROGENEIDAD DEL RENDIMIENTO


Figura 5.4 muestra tres computadoras, todas con la misma plataforma de hardware y sistema operativo. Las computadoras
A y B tienen el mismo nivel de recursos y, por lo tanto, su desempeño es homogéneo. La computadora C tiene diferentes
niveles de recursos, tiene una velocidad de procesamiento de CPU más lenta, más memoria primaria y un disco duro más
pequeño. Las tres computadoras ejecutarán las mismas aplicaciones, con la misma interfaz y soporte del sistema operativo
y los mismos archivos ejecutables (ya que el conjunto de instrucciones de hardware es el mismo en todos los casos). Sin
embargo, las aplicaciones funcionarán de manera diferente en la computadora C que en A o B. Las aplicaciones que
requieren una gran cantidad de espacio de almacenamiento de archivos tienen más probabilidades de exceder la capacidad
en la computadora C, y las aplicaciones de procesamiento intenso tardarán más en ejecutarse. Sin embargo, las aplicaciones
que requieren mucha memoria primaria pueden funcionar mejor en la computadora C.
El ejemplo ilustrado en Figura 5.4 representa el escenario muy común que surge de la actualización gradual y el
reemplazo de sistemas, lo que resulta en situaciones en las que tiene un par de computadoras configuradas con la
misma CPU y sistema operativo, pero, por ejemplo, una ha tenido una expansión de memoria o ha sido equipada
con un disco duro de mayor o menor tiempo de acceso.

Recursos Recursos Recursos

Rendimiento de la CPU Rendimiento de la CPU Rendimiento de la CPU

Tamaño de la memoria Tamaño de la memoria Tamaño de la memoria

Ancho de banda de conexión de red Ancho de banda de conexión de red Ancho de banda de la conexión de red

Tamaño del disco Tamaño del disco Tamaño del disco

Proceso Proceso Proceso

InterfazA InterfazA InterfazA

Operando Operando Operando


InterfazM InterfazM InterfazM
sistema sistema sistema

InterfazX InterfazX InterfazX

Plataforma de hardware Plataforma de hardware Plataforma de hardware

Computadora A Computadora B Computadora C

FIGURA 5.4

Heterogeneidad de desempeño.
5.3 HETEROGENEIDAD 289

5.3.3 HETEROGENEIDAD DE LA PLATAFORMA

Figura 5.5 ilustra un sistema heterogéneo de plataforma. Cada una de las tres computadoras D, E y F tiene una
plataforma de hardware diferente, pero las tres ejecutan variantes compatibles del mismo sistema operativo.

Diferentes plataformas implican que las computadoras tienen diferentes tipos de arquitectura de procesador, aunque diferentes versiones

de la misma familia de procesadores también representan una forma de heterogeneidad de plataforma en los casos en que la interfaz de tiempo

de ejecución es diferente y, por lo tanto, el código de la aplicación debe recompilarse para ejecutarse (por ejemplo, , una versión de la familia de

procesadores puede admitir instrucciones de hardware adicionales que no están disponibles en las demás). Hasta cierto punto, la

heterogeneidad del rendimiento (como efecto secundario) es inevitable en tales casos porque las CPU pueden operar a diferentes velocidades de

procesamiento (el número de instrucciones ejecutadas por segundo) o tener diferentes niveles de optimización interna (como técnicas de

predicción de rama para permitir instrucciones de código de máquina adicionales que se precargarán en la caché antes de la ejecución). La

interfaz entre la plataforma y el sistema operativo es diferente en cada caso; tenga en cuenta las diferentes interfaces X, Y y Z, lo que significa

que se necesitan diferentes versiones del sistema operativo para cada plataforma. Si el sistema operativo es el mismo, como en los tres

escenarios mostrados, la interfaz de proceso con el sistema operativo seguirá siendo la misma; es decir, tendrá las mismas llamadas al sistema

para interactuar con dispositivos, archivos, temporizadores programables, subprocesos, la red, etc. Linux proporciona un muy buen ejemplo de

este escenario en el que el mismo sistema operativo se ejecuta en muchas plataformas diferentes pero proporciona la misma interfaz de proceso

en cada caso. Sin embargo, aunque el código fuente de las aplicaciones podría ser el mismo en los tres escenarios que se muestran en lo que

significa que se necesitan diferentes versiones del sistema operativo para cada plataforma. Si el sistema operativo es el mismo, como en los tres

escenarios mostrados, la interfaz de proceso con el sistema operativo seguirá siendo la misma; es decir, tendrá las mismas llamadas al sistema

para interactuar con dispositivos, archivos, temporizadores programables, subprocesos, la red, etc. Linux proporciona un muy buen ejemplo de

este escenario en el que el mismo sistema operativo se ejecuta en muchas plataformas diferentes pero proporciona la misma interfaz de proceso

en cada caso. Sin embargo, aunque el código fuente de las aplicaciones podría ser el mismo en los tres escenarios que se muestran en lo que

significa que se necesitan diferentes versiones del sistema operativo para cada plataforma. Si el sistema operativo es el mismo, como en los tres

escenarios mostrados, la interfaz de proceso con el sistema operativo seguirá siendo la misma; es decir, tendrá las mismas llamadas al sistema para interactuar con di

Recursos Recursos Recursos

Rendimiento de la CPU Rendimiento de la CPU Rendimiento de la CPU

Tamaño de la memoria Tamaño de la memoria Tamaño de la memoria

Ancho de banda de conexión de red Ancho de banda de conexión de red Ancho de banda de la conexión de red

Tamaño del disco Tamaño del disco Tamaño del disco

Proceso Proceso Proceso

InterfazA InterfazA InterfazA

Operando Operando Operando


InterfazM InterfazN InterfazP
sistema sistema sistema

InterfazX Interfaz InterfazZ

Hardwareplatform1 Hardwareplatform2 Hardwareplatform3

Computadora D Computadora E Computadora F

FIGURA 5.5

Heterogeneidad de plataforma.
290 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Recursos Recursos Recursos

Rendimiento de la CPU Rendimiento de la CPU Rendimiento de la CPU

Tamaño de la memoria Tamaño de la memoria Tamaño de la memoria

Ancho de banda de conexión de red Ancho de banda de conexión de red Ancho de banda de conexión de red

Tamaño del disco Tamaño del disco Tamaño del disco

Proceso Proceso Proceso

InterfazA InterfazB Interfaz C

Operando Operando Operando


InterfazM InterfazM InterfazM
system1 system2 system3

InterfazX Interfaz InterfazZ

Plataforma de hardware Plataforma de hardware Plataforma de hardware

Computadora G Computadora H Computadora J

FIGURA 5.6

Heterogeneidad del sistema operativo.

5.3.4 HETEROGENEIDAD DEL SISTEMA OPERATIVO


Figura 5.6 ilustra la heterogeneidad del sistema operativo. En el escenario que se muestra, las tres computadoras G, H y J
tienen diferentes sistemas operativos pero la misma plataforma de hardware. Los tres sistemas operativos diferentes
tendrán que utilizar cada uno las instalaciones del mismo tipo de plataforma, por lo que habrá diferencias en la interfaz
entre el sistema operativo y el hardware, es decir, las interfaces X, Y y Z, aunque las diferencias están en las formas en que
los diferentes sistemas operativos utilizan los recursos del hardware, en lugar de la interfaz proporcionada por el hardware
en sí (que en realidad es constante en las tres configuraciones mostradas). Aunque el proceso de solicitud tiene el mismo
comportamiento a nivel empresarial en los tres sistemas, la forma en que esto se logra a nivel de código diferirá
ligeramente ya que los diferentes sistemas operativos tendrán diferentes interfaces (fundamentalmente el conjunto de
llamadas al sistema y la sintaxis y semántica de su uso). Por ejemplo, puede haber diferentes versiones de los comandos de
manejo de archivos disponibles, con diferencias en los parámetros que se les pasan. Esto se refleja en la figura mediante las
diferentes interfaces de proceso a sistema operativo A, B y [Link] transferencia de aplicaciones de una de estas computadoras
a otra se denomina transferencia y requeriría la modificación de aquellas partes del código que son sensibles a la
diferencias en las llamadas al sistema operativo admitidas. Como las plataformas de hardware son las mismas en cada caso,
se proporciona la misma interfaz de código de máquina en cada caso. Cambiar el sistema operativo puede afectar la
provisión efectiva de recursos de la computadora y, por lo tanto, impacta en el rendimiento. La forma más notable en la que
esto tiende a ocurrir es en términos de la cantidad de memoria que ocupa el sistema operativo y, por lo tanto, la cantidad de
memoria que queda para que la utilicen los procesos de usuario. Esto se refleja en la figura por la cantidad diferente de
recurso de memoria que se muestra para cada computadora (es decir, se basa en la disponibilidad efectiva de recursos
después de que el sistema operativo ha tomado su parte del recurso).

5.3.5 IMPACTO DE LA HETEROGENEIDAD


Todas las formas de heterogeneidad tienen un impacto potencial en la interoperabilidad. Las aplicaciones que operan en
plataformas heterogéneas o sistemas operativos sistemas heterogéneos dependen, por tanto, de comunicaciones
estandarizadas entre las plataformas. Esto requiere interfaces y protocolos estándar para garantizar que el contenido de
5.3 HETEROGENEIDAD 291

los mensajes y la propia semántica de la comunicación se conservan cuando se pasa un mensaje entre dos sistemas
informáticos diferentes. La API de sockets que opera en la capa de transporte y que se ha discutido en detalle en el
capítulo de vista de comunicación proporciona un buen ejemplo de una interfaz estándar a nivel de proceso. La API
de sockets es compatible con casi todos los sistemas operativos y lenguajes de programación y en casi todas las
plataformas.
Los protocolos TCP y UDP (de la suite de protocolos TCP / IP) son muy buenos ejemplos de protocolos estándar que
facilitan la interoperabilidad entre casi cualquier combinación de plataformas, utilizando la interfaz de sockets a un proceso
como punto final para la comunicación. Estos dos protocolos son extremadamente importantes para Internet; No solo se
utilizan directamente para proporcionar una comunicación personalizada de proceso a proceso (como, por ejemplo, en el
juego de estudio de caso), sino que también se utilizan para construir la mayoría de los mecanismos de comunicación de
capa superior, como RPC, RMI, middleware y servicios web. .
Estos protocolos son ejemplos de los pocos invariantes en los sistemas distribuidos que han resistido la prueba del
tiempo. El hecho de que estén integrados en una gama tan amplia de servicios esenciales y mecanismos de comunicación
de nivel superior refuerza su valor como estándares. Es relativamente seguro asumir que el soporte para estos protocolos
permanecerá durante muchos años: comunicaciones preparadas para el futuro basadas en estos protocolos.

La heterogeneidad del rendimiento es muy común, hasta el punto de que a veces es difícil encontrar equipos con un
rendimiento idéntico. Sin embargo, si este es el único tipo de heterogeneidad presente, las aplicaciones generalmente
funcionarán correctamente en cualquiera de las computadoras host; pero la velocidad y la capacidad de respuesta
generales variarán según la provisión de recursos real. Idealmente, la división funcional entre los componentes de software
y la implementación posterior de estos componentes en los nodos de procesamiento deben coincidir con la provisión de
recursos para garantizar que se logre el rendimiento deseado (pero esto está sujeto a las limitaciones del conocimiento en
tiempo de diseño del tiempo de ejecución eventual sistemas).
La heterogeneidad de la plataforma es cada vez más común, especialmente con la
reciente explosión de popularidad de los dispositivos móviles, incluidos los teléfonos
inteligentes y las tabletas. Los usuarios demandan aplicaciones que funcionen igual en su
computadora personal (PC), su teléfono y su tableta, fundamentalmente porque existe el
deseo de estar “siempre conectado” a sus aplicaciones favoritas, ya sea en casa, en la
oficina o viajando entre ellas. No siempre es posible hacer que las aplicaciones sean
idénticas en las diferentes plataformas, por ejemplo, la interfaz de usuario en un teléfono
inteligente con una pantalla táctil no puede ser idéntica a la interfaz de usuario en una PC
usando un teclado y un mouse. Las diferentes plataformas tienen diferentes niveles de
recursos, y esto a veces es evidente en la forma en que responde el software, por ejemplo,
El soporte para la heterogeneidad de la plataforma puede agregar costos significativos a los proyectos de software. En
primer lugar, será necesario un enfoque de diseño que separe la funcionalidad principal, que es independiente del
dispositivo, de la funcionalidad específica del dispositivo o de la plataforma (generalmente relacionada principalmente con
la interfaz de usuario), que debe desarrollarse por separado para cada plataforma ( ver Sección 5.13 ). Cuantas más
plataformas se admitan y mayor diversidad entre ellas, mayores serán los costos adicionales. En segundo lugar, están los
costos de prueba adicionales. Cada vez que se actualiza el software, se debe probar en todas las plataformas compatibles;
esto en sí mismo puede ser problemático en términos de la mano de obra necesaria y la disponibilidad de una instalación de
prueba en la que las diversas plataformas estén disponibles. Algunas fallas difíciles de rastrear pueden ocurrir solo en una
plataforma, lo que requiere correcciones específicas que luego deben probarse para garantizar que no desestabilicen el
producto cuando se encuentre en las otras plataformas. En algunos proyectos de software, el equipo de pruebas puede ser
más grande que el equipo de desarrollo de software.
292 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

La transferencia de código de una plataforma a otra es menos costosa que el mantenimiento continuo y la
compatibilidad con el código en múltiples plataformas simultáneamente, aunque aún puede ser un desafío y
potencialmente muy costoso. En el caso más simple, en el que el sistema operativo en cada plataforma de destino es el
mismo y las plataformas en sí son similares, es posible que la migración solo requiera que el código fuente (sin cambios)
deba recompilarse para ejecutarse en la nueva plataforma. Sin embargo, si el sistema operativo también es diferente, o
donde las plataformas tienen diferencias significativas, la migración puede requerir un rediseño parcial.
La heterogeneidad del sistema operativo introduce dos tipos principales de diferencias que afectan los procesos: el
primer tipo se encuentra en la interfaz del proceso al sistema operativo y el segundo tipo son las diferencias en el diseño
interno y el comportamiento de los sistemas operativos. Para el primero, el rediseño de las secciones del código de la
aplicación que hacen llamadas al sistema (como exec, leer, escribir y salir) y la posterior recompilación del código puede ser
suficiente. Si la implementación de las llamadas al sistema es similar en los dos sistemas operativos, es posible que no se
produzcan cambios notables en el comportamiento de la aplicación. Sin embargo, para este último, existen problemas
potenciales en el sentido de que los dos sistemas operativos pueden tener diferentes niveles de robustez o uno puede tener
debilidades de seguridad que el otro puede no tener. Por ejemplo, un sistema operativo puede ser vulnerable a ciertos virus
y otras amenazas a las que el otro es inmune. También podría haber efectos en el rendimiento de las aplicaciones debido a
las diferencias en los comportamientos del sistema operativo, incluida la programación y la asignación de recursos.

5.3.6 PUERTA DE SOFTWARE


Portar aplicaciones de un sistema a otro puede ser muy complejo porque los dos sistemas anfitriones pueden ser
muy diferentes en las diversas formas discutidas anteriormente. El resultado final puede ser aplicaciones que son
funcionalmente similares, pero algunos aspectos como la interfaz de usuario o el tiempo de respuesta pueden ser
notablemente diferentes debido a la disponibilidad de recursos. Los navegadores proporcionan un buen ejemplo en
el que, esencialmente, la misma funcionalidad está disponible pero con un aspecto diferente en las distintas
plataformas en las que se ejecutan. La tecnología de navegador se estableció inicialmente en las PC de uso general
(computadoras portátiles y de escritorio) durante muchos años, pero ahora se ha adaptado para operar de la misma
manera bien conocida en dispositivos móviles, que tienen diferentes procesadores y sistemas operativos y, en
general, menos recursos en términos de memoria, velocidad de procesamiento, pantallas más pequeñas,

Una máquina virtual (VM) es un programa de software que se encuentra entre los procesos de la aplicación y la computadora subyacente.

En lo que respecta al programador de la computadora, la VM es el proceso en ejecución. La máquina virtual en realidad proporciona un entorno

de tiempo de ejecución para aplicaciones que emula la computadora subyacente real; podemos decir que las aplicaciones se ejecutan en o sobre

la máquina virtual. Debido a que los procesos de la aplicación interactúan con la máquina virtual en lugar de la computadora física, la máquina

virtual puede enmascarar la verdadera naturaleza de la computadora física y puede permitir que se ejecuten programas compilados en

diferentes plataformas. Al proporcionar una maqueta del entorno en el que la aplicación necesita para ejecutarse, el enfoque de VM evita la

necesidad de portar per se. El enfoque de VM es clave para la forma en que se ejecutan los programas de Java. Una aplicación se compila en un

formato especial llamado código de bytes de Java; este es un formato intermedio que es independiente de la plataforma informática. Una

máquina virtual específica de Java (JVM) interpreta el código de bytes (es decir, ejecuta las instrucciones del código de bytes) de la misma manera

independientemente del entorno físico; por lo tanto, la portabilidad es un problema mucho menor para los programas Java en general que para

los programas escritos en otros lenguajes. El enfoque de VM (o JVM), por supuesto, requiere que una VM (o JVM) esté disponible para cada una

de las plataformas en las que desea ejecutar las aplicaciones. Las VM (o JVM) en sí mismas son específicas de la plataforma; se compilan y

ejecutan como la portabilidad es un problema mucho menor para los programas Java en general que para los programas escritos en otros

lenguajes. El enfoque de VM (o JVM), por supuesto, requiere que una VM (o JVM) esté disponible para cada una de las plataformas en las que desea ejecutar las aplicaciones
5.4 HARDWARE Y ARQUITECTURAS A NIVEL DE SISTEMAS 293

proceso regular, nativo, en cualquier plataforma para la que estén diseñados. Las máquinas virtuales y la JVM se tratan con más
detalle más adelante en este capítulo.
Middleware proporciona varios servicios a aplicaciones que desacoplan algunos aspectos de su funcionamiento de la
máquina física subyacente, especialmente con respecto al acceso a recursos que pueden ser locales (en la misma
computadora) o remotos. De esta forma, el middleware permite que los procesos se ejecuten de la misma forma lógica
independientemente de su ubicación física. Por ejemplo, el middleware puede ubicar automáticamente los recursos que el
proceso necesita o puede pasar mensajes automáticamente de un proceso a otro sin que tengan que tener una conexión
directa o incluso conocer la ubicación de cada uno (consulte Sección 5.5.1 en este capítulo). El middleware puede
implementarse en diferentes plataformas de hardware, de modo que un proceso que se ejecuta en un tipo de plataforma
puede usar de manera transparente recursos ubicados en una computadora con un tipo de plataforma diferente. Sin
embargo, el middleware no ejecuta realmente las instrucciones de las aplicaciones de la forma en que lo hace una máquina
virtual y, por lo tanto, no resuelve el problema de portabilidad directamente. Sin embargo, debido a que el middleware
puede permitir el uso remoto de recursos que se encuentran en diferentes plataformas, así como la comunicación entre
procesos en diferentes tipos de plataformas, ofrece una solución indirecta a la portabilidad, la del acceso remoto
transparente, sin que el proceso se mueva realmente a la otra plataforma. Más adelante en este capítulo se proporciona una
descripción general del middleware y en el Capítulo 6 se proporciona una discusión más detallada.

5.4 HARDWARE Y ARQUITECTURAS A NIVEL DE SISTEMAS


Las aplicaciones distribuidas comprenden componentes de software que se encuentran dispersos en las distintas
computadoras del sistema. Para que estos componentes funcionen como una aplicación única coherente, a diferencia de los
componentes aislados que hacen lo suyo, es necesario que existan algunos medios para que los componentes se
comuniquen. Para que esto sea posible, debe haber alguna forma de conexión entre los procesadores subyacentes, en los
que se ejecuta el software de soporte de comunicación.
Hay dos enfoques fundamentalmente diferentes para conectar los procesadores. Las arquitecturas
estrechamente acopladas son aquellas en las que los procesadores son parte de un único sistema físico y, por lo
tanto, la comunicación se puede implementar mediante conexiones directas dedicadas. En tales sistemas, los
procesadores pueden estar equipados con interfaces (o canales) de comunicación especiales diseñados para la
interconexión directa con otros procesadores, sin la necesidad de una red informática. Los procesadores comparten
los recursos de la computadora, incluidos el reloj, la memoria y los dispositivos de E / S.
Las arquitecturas de computadora autónomas son aquellas en las que cada procesador es el núcleo de una computadora completa con su

propio conjunto de recursos dedicados. La PC, el teléfono inteligente, la tableta y las computadoras portátiles son ejemplos de esta clase de

computadora. Los dispositivos independientes necesitan una red externa para comunicarse. Es necesario que haya una interfaz de red que

conecte cada computadora a la red, así como un software de comunicación especial en cada computadora para enviar y recibir mensajes a través

de la red. Esta forma de conectar las computadoras juntas produce un acoplamiento menos estrecho y más flexible; por lo tanto, se denomina

acoplamiento suelto.

5.4.1 SISTEMAS TOTALMENTE ACOPLADOS (HARDWARE)


La principal característica de los sistemas estrechamente acoplados es que comprenden varias unidades de procesador
integradas juntas en la misma computadora física. Esto significa que se pueden ejecutar varios subprocesos de código de
programa al mismo tiempo, es decir, en paralelo, ya que cada procesador puede ejecutar una instrucción en cada
294 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

hora de caminar. En estas arquitecturas, los canales de comunicación entre unidades procesadoras son muy cortos y pueden
implementarse utilizando tecnología similar a la de las unidades procesadoras, lo que significa que la comunicación puede tener lugar
a velocidades similares a los accesos a la memoria. De hecho, dado que los procesadores suelen tener acceso compartido a al menos
parte de la memoria del sistema, es posible que los subprocesos del programa se comuniquen realmente utilizando la memoria. Por
ejemplo, si un proceso escribe un nuevo valor en una variable particular almacenada en una ubicación de memoria compartida, todos
los demás procesos pueden leer la variable, sin la necesidad de enviar específicamente un mensaje a cada proceso. Las principales
ventajas de esta forma de comunicación son que tiene la misma confiabilidad casi perfecta que los accesos a la memoria y que no se
convierte en un cuello de botella en términos de rendimiento; escribir en la memoria es efectivamente la misma operación que enviar
un valor de datos a otro procesador. Esto significa que se pueden desarrollar aplicaciones paralelas para resolver algoritmos en los
que existe una alta intensidad de comunicación (una alta tasa de comunicación entre los procesadores). Por el contrario, estas
aplicaciones no funcionan tan bien en arquitecturas poco acopladas debido a la presencia de una tecnología de red externa que
opera a velocidades más bajas que los accesos a la memoria, tiene mayor latencia debido a mayores distancias físicas y también es
menos confiable. En arquitecturas estrechamente acopladas, generalmente hay un solo reloj compartido y, por lo tanto, es posible
sincronizar procesos con precisión en términos de eventos a nivel de aplicación y acciones resultantes realizadas. Cada procesador
ejecuta instrucciones exactamente a la misma velocidad;

5.4.2 SISTEMAS DE ACOPLAMIENTO FLEXIBLE (HARDWARE)


Este libro se centra en aplicaciones distribuidas que se ejecutan en sistemas poco acoplados. Estos sistemas constan de una
serie de ordenadores autónomos capaces de funcionar independientemente de los demás. Un ejemplo perfecto de esto es
la PC que estoy usando para escribir el libro. La computadora tiene su propia fuente de alimentación, procesador, reloj,
memoria, almacenamiento en disco duro, sistema operativo y dispositivos de E / S. Sin embargo, el hecho de que la
computadora sea autónoma no significa necesariamente que la computadora pueda hacer lo que yo requiero de ella de
forma aislada. La mayoría de las aplicaciones que se utilizan en los negocios modernos, así como en los pasatiempos, el
entretenimiento y las redes sociales, requieren acceso a los datos almacenados en otras computadoras y también requieren
un medio para comunicarse con otros usuarios, a través de las computadoras que están usando. Por lo tanto, casi todas las
computadoras tienen una conexión de red para soportar los requisitos de comunicación de aplicaciones y datos
distribuidos. Esta forma de acoplamiento se denomina "suelta" porque la red es externa a la propia computadora. La
comunicación a través de redes es más lenta y menos confiable que en sistemas estrechamente acoplados. Sin embargo, la
comunicación en sistemas débilmente acoplados se puede reconfigurar de manera flexible para que una computadora en
particular pueda conectarse lógicamente a cualquier otra que sea accesible en la red.

Cada computadora tiene su propio conjunto de recursos, lo cual es beneficioso en


general, porque el programador local tiene el control de la forma en que los recursos (como
la memoria y los ciclos de computación del procesador) se comparten entre los procesos
locales. Sin embargo, el hecho de que cada computadora también tenga su propio reloj que
gobierna la velocidad precisa a la que se ejecutan las instrucciones y también se utiliza para
realizar un seguimiento del tiempo del reloj de pared (la noción de tiempo real del mundo
real) presenta algunos desafíos de sincronización cuando se ejecuta. aplicaciones
distribuidas. Por ejemplo,
5.4 HARDWARE Y ARQUITECTURAS A NIVEL DE SISTEMAS 295

Reloj

UPC UPC UPC

Memoria caché Memoria caché Memoria caché

Memoria compartida

(a) Procesadores estrechamente acoplados con memorias caché privadas y memoria principal compartida

Memoria caché Memoria caché Memoria caché


Reloj

Reloj

Reloj
UPC UPC UPC

La red

(B) Los procesadores débilmente acoplados utilizan la red para comunicarse

FIGURA 5.7

Arquitecturas de hardware estrecha y débilmente acopladas.

relojes sincronizados. Los desafíos de la sincronización del reloj y algunas técnicas para superar estos
desafíos se analizan en el Capítulo 6.
Otro desafío que surge para el uso de computadoras interconectadas pero autónomas es que pueden fallar de
forma independiente. Las fallas que ocurren cuando las aplicaciones están inactivas no corrompen los datos y, por
lo tanto, son relativamente fáciles de tratar. Sin embargo, considere la falla de una computadora durante una
transferencia de datos. Si los datos se corrompen o no depende de una serie de factores que incluyen el momento
exacto en el que ocurre la falla y la medida en que el mecanismo de comunicación en uso fue diseñado para ser
sólido con respecto al mantenimiento de la integridad de los datos.
Figura 5.7 ilustra los conceptos principales de arquitecturas de hardware estrecha y débilmente acopladas. En realidad,
existen muchas variaciones de arquitecturas estrechamente acopladas, las principales diferencias con respecto al acceso a
la memoria y la forma en que se comunican los procesadores. En algunos diseños, se comparte toda la memoria, mientras
que en otros, también hay un caché privado por procesador (como se muestra), y algunos diseños tienen canales de
comunicación dedicados entre los procesadores.

5.4.3 PROCESAMIENTO EN PARALELO

El procesamiento paralelo es una clase especial de aplicación distribuida, que se describe brevemente aquí para que sea
más completa.
Una aplicación paralela generalmente comprende una serie de procesos que realizan todos los mismos cálculos pero
con datos diferentes y en diferentes procesadores, de modo que la cantidad total de computación realizada por unidad de
tiempo es significativamente mayor que si se usara un solo procesador.
La cantidad de comunicación que se produce entre los procesos depende en gran medida de la naturaleza de la
aplicación en sí. En la mayoría de las aplicaciones paralelas, los datos en cada nodo de procesamiento no son
296 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

procesado de forma aislada; En general, existe la necesidad de interactuar con el cálculo de valores de datos en otros nodos,
que representan regiones limítrofes del espacio de datos de la aplicación.
Un ejemplo clásico de una aplicación de procesamiento paralelo de la que la mayoría de nosotros nos
beneficiamos a diario es el pronóstico del tiempo, que utiliza técnicas especializadas como la dinámica de fluidos
computacional (CFD). El área geográfica que se estudiará se divide en pequeñas regiones, que se subdividen en
celdas cada vez más pequeñas. El pronóstico real del tiempo en un momento particular en el futuro, en una celda en
particular, se basa no solo en el historial de las condiciones climáticas en la celda en los momentos previos al tiempo
de pronóstico, sino también en las condiciones climáticas en las celdas vecinas. en cada uno de esos momentos, lo
que influye en el clima en nuestra celda de interés. Las condiciones meteorológicas en las celdas vecinas directas de
nuestra celda de interés también se ven afectadas por las condiciones en las celdas vecinas de las celdas vecinas en
cada paso de tiempo, y así continúa. t se calcula en función del estado de la celda en el momento t y también
1
el
estado de las celdas vecinas en el momento t. Una
0
vez que el nuevo estado de las células en el momento t se0
calcula, se convierte en el punto de partida
1
de la siguiente iteración para calcular el estado de las celdas en el
momento t. La cantidad total de cálculo está
2
determinada por la complejidad del algoritmo real y el número de
celdas en el modelo y el número de pasos de tiempo (por ejemplo, el pronóstico del tiempo real para una región del
tamaño del Reino Unido puede funcionar con una celda de datos geográficos tamaño de quizás 1,5 km 2). La cantidad
de comunicación depende del grado de dependencia entre las celdas durante los pasos de iteración del algoritmo.

Una aplicación paralela que tiene una alta relación de cálculo a comunicación (es decir, hace
muchos cálculos entre cada episodio de comunicación) puede ser adecuada para operar en
sistemas poco acoplados. Sin embargo, una aplicación en la que la comunicación se produce a
una velocidad alta con una cantidad baja de cálculo entre la comunicación solo es adecuada para
la ejecución en arquitecturas especializadas estrechamente acopladas. Si se ejecuta en un
sistema débilmente acoplado, dichas aplicaciones tienden a progresar más lentamente,
posiblemente incluso más lento que una versión equivalente no paralela en un solo procesador.
Esto se debe a la latencia de la comunicación y a que el requisito de comunicación total puede
exceder el ancho de banda de comunicación disponible.

5.5 ARQUITECTURAS DE SOFTWARE


En las aplicaciones distribuidas, la lógica empresarial se divide en dos o más componentes. Un buen diseño asegurará que
esto se haga para lograr una "separación de preocupaciones" en la mayor medida posible. Con esto, se quiere decir que es
ideal dividir el límite lógico de los componentes sobre una base funcional en lugar de sobre una base más abstracta. Si la
lógica se divide en componentes de forma arbitraria (por ejemplo, quizás para tratar de mantener todos los componentes
del mismo tamaño), es probable que haya más comunicación e interdependencia entre los componentes resultantes. Esto
puede conducir a una estructura más compleja y frágil porque los problemas que afectan a un componente también afectan
a los componentes acoplados directamente y pueden propagarse a través de una cadena de componentes.

Un diseño en el que los límites de los componentes están alineados con los límites del comportamiento funcional
natural puede dar como resultado una estructura mucho menos acoplada en la que las funcionalidades individuales se
pueden reemplazar o actualizar sin desestabilizar toda la arquitectura, y donde las fallas pueden ser contenidas, de modo
que un componente fallado lo hace. no conducir a un colapso de efecto dominó. La división de la lógica empresarial a lo
largo de líneas funcionales también permite apuntar a los mecanismos de robustez y recuperación (como la replicación de
5.5 ARQUITECTURAS DE SOFTWARE 297

servicios) a áreas específicas del sistema que son más críticas para el funcionamiento del sistema o quizás son más sensibles
a eventos externos y, por lo tanto, es más probable que fallen.
La forma en que la lógica empresarial se divide funcionalmente entre los componentes es, en muchos
casos, el factor más importante que influye en el rendimiento, la solidez y la eficiencia de las aplicaciones
distribuidas. Esto se debe a que afecta la forma en que se produce la vinculación entre los componentes y el
alcance y la complejidad de la comunicación. Si se hace mal, la intensidad de la comunicación puede ser
varias veces mayor que el nivel óptimo.
Sin embargo, es necesario implementar algunas funciones en varios componentes, debido a la forma en que la
aplicación está estructurada u opera. Por ejemplo, la lógica empresarial de una aplicación cliente-servidor (CS) puede
distribuir la gestión y el almacenamiento de información de estado entre los dos tipos de componentes. El estado que solo
se necesita en el lado del cliente puede administrarse dentro del componente del cliente (mejorando la escalabilidad porque
se reduce la carga de trabajo del servidor por cliente), mientras que el estado compartido debe administrarse y almacenarse
en el lado del servidor porque se accede a él mediante transacciones que involucran varias clientela.

5.5.1 ACOPLAMIENTO ENTRE COMPONENTES DE SOFTWARE


Hay una variedad de formas en las que varios componentes de software (que se ejecutan como procesos) se
pueden conectar entre sí para lograr una determinada configuración o estructura. La lógica y el comportamiento
del negocio a nivel de aplicación se definen, por tanto, por la lógica colectiva de los componentes y la comunicación
entre ellos. El término "acoplamiento" se utiliza para describir las formas en que los diversos procesos se conectan
entre sí para lograr una conectividad (lógica) de nivel empresarial superior. La naturaleza de este acoplamiento es
un aspecto crítico del diseño exitoso de sistemas distribuidos.
Como se discutió anteriormente, las conexiones excesivas y las dependencias directas entre componentes son
generalmente problemáticas en términos de escalabilidad y robustez. Las dependencias directas también inhiben la
reconfiguración dinámica, que es cada vez más importante en aplicaciones muy complejas y ricas en funciones y en
dominios de aplicaciones en los que el entorno operativo es en sí mismo muy dinámico.
Hay varias formas de acoplamiento, como se explica a continuación. Si el acoplamiento está apretado o suelto está determinado por el

grado de flexibilidad de tiempo de ejecución incorporada en el momento del diseño.

Acoplamiento estrecho (o fijo) se caracteriza por el diseño de conexiones decididas en el tiempo entre componentes
específicos. Las referencias explícitas a otros componentes introducen dependencias directas entre los componentes, lo que
significa que la aplicación solo puede funcionar si todos los componentes requeridos (según su arquitectura de tiempo de
diseño fijo) están disponibles. Si un componente falla, los otros componentes que dependen de él fallan o al menos no
pueden proporcionar las funcionalidades a las que contribuye el componente fallado. Por lo tanto, el diseño estrechamente
acoplado tiende a aumentar la sensibilidad a fallas, reducir la flexibilidad, reducir la escalabilidad, aumentar la dificultad del
mantenimiento e inhibir la reconfigurabilidad del tiempo de ejecución.
Acoplado libremente (desacoplado) los componentes no tienen conexiones con otros componentes
específicos decididos en el momento del diseño. Esta forma de acoplamiento se caracteriza por servicios
intermediarios, que proporcionan comunicación entre componentes (como middleware) y / o por el uso de
mecanismos de descubrimiento de componentes dinámicos (como publicidad de servicios). Los componentes están
acoplados con referencias indirectas. Este es un enfoque flexible en tiempo de ejecución, ya que es posible que el
servicio intermediario modifique las referencias a otros componentes en función de la disponibilidad en el
momento de otros componentes; por lo tanto, los componentes no dependen directamente de instancias
específicas de otros componentes o procesos. Por ejemplo, un cliente podría asignarse a una de las muchas
instancias de un servicio, según la disponibilidad en el momento en que se realiza la solicitud del servicio.
298 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

componentes de servicio individuales. El mapeo de intercomponentes también puede basarse en una descripción de la funcionalidad
requerida en lugar de basarse en un ID de componente específico, por lo tanto, en el tiempo de ejecución, el intermediario (como el
middleware) puede conectar componentes basándose en una coincidencia de lo que uno necesita y lo que proporciona el otro .

Dado que el acoplamiento flexible utiliza servicios o mecanismos externos para proporcionar el mapeo entre pares de
componentes, tiene el potencial de hacer que el acceso y la ubicación de las aplicaciones sean transparentes. Las aplicaciones poco
acopladas son más fáciles de mantener, ya que se pueden admitir actualizaciones cambiando la asignación de tiempo de ejecución
para intercambiar la nueva versión de un componente en la posición que ocupaba la versión anterior. Las aplicaciones acopladas de
forma flexible también son extensibles, ya que se pueden agregar nuevos componentes con nueva funcionalidad sin rediseñar los
otros componentes o recompilar el sistema. Ver Figura 5.8 .
Figura 5.8 ilustra las ventajas del acoplamiento suelto. El mapeo dinámico facilita la transparencia de la
ubicación, ya que el cliente no necesita conocer la ubicación del componente del servicio. Esto permite la
reasignación automática a una instancia de servicio diferente si falla la que se usa actualmente (como entre horas
t1y t cuando
3
la instancia del servidor A del servicio falla y las solicitudes del cliente se reasignan a la instancia B del
mismo servicio) y también se reasignan a una versión mejorada de un servicio (como entre horas t y 3
t 5cuando se actualiza el servicio y las solicitudes de los clientes posteriores se asignan a una nueva instancia de servidor de
la versión 2). La transparencia de acceso también se proporciona en algunos casos en los que el servicio de conectividad
maneja las diferencias en las interfaces del servicio de la aplicación (que surgen, por ejemplo, durante una actualización del
servicio) de modo que los componentes del cliente permanezcan sin cambios. Esto es muy importante cuando hay un gran
número de clientes implementados y actualizarlos todos en el paso de cada actualización del servidor sería costoso en
términos de logística, tiempo y esfuerzo y arriesga la situación en la que diferentes versiones del cliente podrían estar en
uso en el sistema al mismo tiempo.
Las conexiones lógicas pueden ser directas entre componentes en comunicación o pueden facilitarse indirectamente
mediante componentes intermedios:
Acoplamiento directo se caracteriza por el hecho de que las conexiones de nivel de proceso a proceso se
corresponden con la comunicación de nivel empresarial de la aplicación. Las conexiones lógicas de la capa de
transporte se asignan directamente a la conectividad de nivel superior. Por ejemplo, puede haber una conexión TCP
o UDP directa entre los componentes de nivel empresarial.

Servidor Versión1 del servidor, InstanciaA


Mapeo en t 1
versión En uso en el momento t 1

1 Se bloquea en el momento t 2

Servidor
Mapeo en t 3 Versión 1 del servidor, InstanciaB
versión
En uso en el momento t 3
Cliente 1

Servicio de conectividad
(por ejemplo integrado
intomiddleware)
Servidor Versión del servidor 2 (actualizado)

Mapeo en t 5 versión Instalado en el momento t 4

2 En uso en el momento t 5

FIGURA 5.8

Mapeo dinámico en sistemas débilmente acoplados.


5.5 ARQUITECTURAS DE SOFTWARE 299

Acoplamiento indirecto describe la situación en la que los componentes interactúan a través de un intermediario. Un sistema
de negociación de acciones proporciona un ejemplo en el que los clientes tienen conexiones privadas pero ven los efectos de las
transacciones de otros clientes (en forma de cambios en el precio de las acciones), lo que puede dar lugar a más transacciones. Otro
ejemplo lo proporciona un juego multijugador alojado en un servidor central, donde los clientes del juego son conscientes de la
presencia del otro en el nivel de la aplicación (están conectados lógicamente por el hecho de que son oponentes en el mismo juego)
pero no están directamente conectados entre sí como componentes. Cada cliente está conectado solo al servidor y cualquier
comunicación entre los clientes se pasa al servidor y se reenvía al otro cliente. La aplicación de juegos de casos de uso proporciona un
ejemplo útil de esta forma de acoplamiento. Otro ejemplo es el correo electrónico, en el que las personas utilizan sus clientes de
correo electrónico para enviarse mensajes de correo electrónico entre sí (la conexión lógica es en términos de la conversación de
correo electrónico). Cada uno de los clientes de correo electrónico se conecta al servidor de correo electrónico respectivo de los
usuarios, que contiene su bandeja de entrada de correo y también envía correo saliente; ver Figura 5.9 .

Figura 5.9 utiliza el correo electrónico para ilustrar el acoplamiento indirecto. Los usuarios (en realidad, los procesos de cliente de
correo electrónico que utilizan) tienen una conexión lógica en el paso de mensajes de correo electrónico a nivel de aplicación. Los
clientes de correo electrónico no están conectados directamente, ni siquiera si ambos usuarios tienen el mismo servidor de correo
electrónico. En la figura, hay dos intermediarios entre los clientes de correo electrónico. Cada cliente está directamente acoplado a su
respectivo servidor de correo electrónico y los dos servidores están directamente acoplados entre sí. Tenga en cuenta que esto no
afecta si los componentes acoplados directamente están acoplados apretada o débilmente; esto depende de cómo se realice la
asociación entre los componentes (por ejemplo, podría haber un servicio intermediario como middleware que proporcione
conectividad dinámica).
Acoplamiento aislado describe la situación en la que los componentes no están acoplados entre sí y no se
comunican entre sí aunque forman parte del mismo sistema. Por ejemplo, un par de clientes, cada uno de ellos
conectado al mismo servidor, no necesitan comunicarse directamente ni siquiera ser conscientes de que existe el
otro. Considere, por ejemplo, dos usuarios de un sistema bancario en línea. Cada uno de sus procesos cliente
accede al servidor bancario, pero no existe una asociación lógica entre los dos clientes; cada uno tiene conexiones
lógicas independientes con el banco. El ejemplo de correo electrónico que se muestra en
Figura 5.9 proporciona el marco para otro ejemplo: considere dos usuarios que no se conocen cada uno

Los clientes de correo electrónico están acoplados indirectamente a través de los servidores de correo electrónico.

Correo electrónico Correo electrónico Correo electrónico Correo electrónico

cliente servidor servidor cliente


A A B B

Comunicación directa entre servidores de correo electrónico


Usuario A Usuario B
a través del protocolo de transferencia de correo de Internet:

Protocolo simple de transferencia de correo (SMTP)

Comunicación directa entre el cliente de correo electrónico de un usuario y el

servidor de correo electrónico, a través de un protocolo de recuperación de

correo electrónico y administración de buzón, como:

Protocolo de oficina postal (POP) o


Protocolo de acceso a mensajes de Internet (IMAP)

FIGURA 5.9

El envío de correo electrónico implica varios componentes. Los clientes de correo electrónico están acoplados indirectamente.
300 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

otros y nunca se envíen correos electrónicos entre sí. Los respectivos procesos del cliente de correo electrónico son parte
del mismo sistema pero no tienen una asociación lógica en este caso y, por lo tanto, los procesos no están acoplados entre
sí.
Figura 5.10 ilustra las posibles variaciones de acoplamiento, basándose en una aplicación CS como ejemplo. La
parte (a) muestra el acoplamiento directo en el que la conectividad de nivel empresarial se refleja directamente en
la conexión de proceso a proceso. Esta es una configuración muy común en aplicaciones a pequeña escala. La parte
(b) muestra el acoplamiento indirecto utilizando un componente específico como intermediario que reenvía la
comunicación entre los procesos conectados. El componente central es parte de la aplicación y participa en, y
posiblemente administra, la conectividad a nivel empresarial; esto se refleja en la figura al mostrar que la conexión
lógica empresarial pasa a través del componente del servidor. El juego de casos de uso proporciona un ejemplo de
esto, ya que el servidor necesita observar los cambios en el estado del juego, actualizar su propia representación del
estado del juego, y reenviar los movimientos realizados por un cliente al otro. El servidor también debe verificar las
condiciones del final del juego, es decir, un cliente ganó o fue un empate y también debe regular la actividad por
turnos de los clientes. La parte (c) comprende las partes (a) y (b) para ilustrar

Cliente Servidor

(a) Acoplamiento directo


(C) Acoplamiento estrecho

Cliente Servidor Cliente

Cliente Servidor

(B) Acoplamiento indirecto

Cliente
Middleware

Bajo acoplamiento

Cliente Servidor
(un servicio o mecanismo externo
(mi) conecta los procesos)

Aislado (cliente a cliente) (cada


Cliente
cliente está directamente
Cliente Servidor Cliente
acoplado al servidor)
(D)
Clave

Proceso para procesar la conexión

Conexión de proceso a middleware Middleware

Conexión lógica empresarial


Acoplamiento suelto de una indirecta
(F) aplicación acoplada

FIGURA 5.10

Variaciones de acoplamiento, ilustradas en el contexto de una aplicación cliente-servidor.


5.5 ARQUITECTURAS DE SOFTWARE 301

Acoplamiento estrecho entre componentes, es decir, donde los componentes se conectan directamente a otros componentes específicos con los

que tienen una relación lógica empresarial. La arquitectura a nivel de aplicación está "diseñada" en estos componentes de manera que se

conecten a otros componentes de una manera predecida. La parte (d) muestra que los clientes que utilizan un servicio común, donde cada

interacción del cliente con el servicio es privada para ese cliente específico, están aislados (es decir, los clientes no están acoplados entre sí) a

nivel empresarial. Cada cliente obtiene el servicio del servidor sin interacción ni conocimiento de la presencia de los otros clientes. La parte (e)

muestra cómo un mecanismo o servicio de conectividad externo, como middleware, se puede utilizar para proporcionar conectividad entre

procesos sin que tengan que formar o gestionar la conectividad directamente entre ellos. El mecanismo de conectividad no es parte de la

aplicación y no participa en la conectividad a nivel empresarial; su función es transmitir mensajes de forma transparente entre los dos

componentes sin conocer su significado o contenido. Este es un medio mucho más flexible de conectar procesos y es muy importante para

aplicaciones a gran escala o reconfigurables dinámicamente. Cada uno de los modos de acoplamiento directo e indirecto se puede lograr de

formas poco acopladas, como lo confirma la parte (f) de la figura, donde los mensajes se pasan a través del middleware en lugar de directamente

entre los componentes, pero las relaciones de los componentes en el nivel de la lógica empresarial no se modifican. El mecanismo de

conectividad no es parte de la aplicación y no participa en la conectividad a nivel empresarial; su función es transmitir mensajes de forma

transparente entre los dos componentes sin conocer su significado o contenido. Este es un medio mucho más flexible de conectar procesos y es

muy importante para aplicaciones a gran escala o reconfigurables dinámicamente. Cada uno de los modos de acoplamiento directo e indirecto

se puede lograr de formas poco acopladas, como lo confirma la parte (f) de la figura, donde los mensajes se pasan a través del middleware en lugar de directamente e

En general, la escalabilidad está inversamente relacionada con el grado de acoplamiento entre componentes
debido a los gastos generales de comunicación y sincronización que introduce el acoplamiento. Por lo tanto, el
acoplamiento excesivo puede verse como un costo y debe evitarse por diseño cuando sea posible. Por lo tanto, para
sistemas grandes, el diseño escalable tenderá a requerir que la mayoría de los componentes estén aislados entre sí
y que cada componente solo esté acoplado con el conjunto mínimo necesario de otros componentes.

Figura 5.11 muestra dos posibles acoplamientos diferentes entre componentes de un mismo sistema. La parte
(a) muestra una configuración de árbol que tiende a ser eficiente siempre que los canales de comunicación
naturales no se vean obstaculizados por tener que reenviar mensajes a través de varios componentes. Esto requiere
un buen diseño para que el caso en el que un mensaje se transmita desde un nodo hoja hasta la raíz del árbol y de
una rama diferente a otra hoja sea una ocurrencia rara y que la mayor parte de la comunicación se produzca entre
pares de componentes adyacentes en el árbol. árbol. La parte (b) muestra un mapeo significativamente más
complejo, que introduce un mayor grado de dependencia entre componentes. Puede ser que la complejidad de la
conectividad sea inherente a la lógica de la aplicación y no se pueda simplificar aún más, aunque tal mapeo debe
analizarse cuidadosamente.

Configuración tipo malla


(a) Configuración de árbol
(B)
FIGURA 5.11

Diferentes complejidades del acoplamiento de componentes.


302 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

5,6 TAXONOMÍA DE LAS CLASES DE ARQUITECTURA DE SOFTWARE


Las diversas actividades realizadas por una aplicación se pueden dividir genéricamente en tres líneas
principales de funcionalidad: la primera sección está relacionada con la interfaz de usuario, la segunda
sección es la lógica empresarial de la aplicación y la tercera sección es la funcionalidad relacionada con el
almacenamiento de y acceso a los datos. Estas son tres áreas de funcionalidad que generalmente están
presentes en todas las aplicaciones hasta cierto punto, y si sus descripciones se mantienen lo
suficientemente generales, tienden a cubrir todas las actividades comunes. Esta amplia categorización es
muy útil como medio para describir y comparar la distribución de funcionalidades entre los diversos
componentes de un sistema. Tenga en cuenta que la descripción en términos de estos capítulos se mantiene
intencionalmente en un nivel alto y, por lo tanto, es más útil para describir y clasificar el enfoque adoptado
en la distribución (es decir,

5.6.1 APLICACIONES DE UN SOLO NIVEL


Una aplicación de un solo nivel es aquella en la que las tres principales líneas de funcionalidad se combinan en un solo componente,
es decir, no hay distribución. Estas aplicaciones tienden a ser servicios públicos locales que tienen una funcionalidad restringida. En
términos de aplicaciones comerciales, el diseño de un solo nivel se está volviendo bastante raro, ya que carece de las cualidades de
conectividad y de intercambio de datos necesarias para lograr los comportamientos más avanzados necesarios en muchas
aplicaciones.
Figura 5.12 ilustra el mapeo de las tres principales líneas de funcionalidad en un solo componente de
aplicación. En ocasiones, estas aplicaciones se denominan aplicaciones independientes.

5.6.2 APLICACIONES DE DOS NIVELES


Las aplicaciones de dos niveles dividen las principales líneas de funcionalidad en dos tipos de componentes. El ejemplo más
común de una aplicación de dos niveles es la arquitectura CS (discutida en detalle más adelante).
Figura 5.13 muestra algunas de las posibles variaciones de distribución de funcionalidad para aplicaciones CS. Tenga en
cuenta que la figura es solo ilustrativa y no pretende proporcionar una indicación precisa en cuanto a la proporción de
esfuerzo de procesamiento dedicado a cada una de las hebras funcionales.
Las aplicaciones peer-to-peer (también discutidas más adelante en detalle) pueden considerarse un híbrido entre los
enfoques de un solo nivel y de dos niveles. Esto se debe a que cada instancia de pares es esencialmente autónoma y, por lo
tanto, tiene elementos de las tres hebras de funcionalidad. Sin embargo, para cooperar como pares, debe haber

Clave
U D
U: interfaz de usuario
B — Lógica empresarial

D: acceso a los datos


B

FIGURA 5.12

El diseño de un solo nivel coloca todas las principales líneas de funcionalidad en un tipo de un solo componente.
5,6 TAXONOMÍA DE LAS CLASES DE ARQUITECTURA DE SOFTWARE 303

Caso distribuido uniformemente en el que la lógica empresarial se

U D distribuye tanto en el cliente como en el servidor, y donde el cliente

B D gestiona los datos locales mientras que el servidor es responsable de

mantener los datos compartidos de forma centralizada. El cliente

B proporciona la interfaz de usuario.

Caso extremo de servidor pesado donde el cliente es efectivamente

solo un portal de usuario, toda la lógica comercial y el acceso a los


U B D datos se realiza mediante el proceso del servidor

Caso extremo de cliente pesado en el que el servidor


proporciona acceso a datos remotos / compartidos, pero toda
U B D la lógica empresarial y la funcionalidad de la interfaz de
usuario se realiza en el cliente.

Clave

U: interfaz de usuario
B — Lógica empresarial
Cliente Servidor
D: acceso a los datos

FIGURA 5.13

El diseño de dos niveles distribuye las principales líneas de funcionalidad entre los tipos de dos componentes.

ser alguna comunicación entre instancias, por ejemplo, es común que las aplicaciones peer-to-peer faciliten el intercambio
de datos, donde cada par tiene un subconjunto de datos y lo pone a disposición de otros pares bajo demanda (ver Figura
5.14 ). Como Figura 5.14 implica que cada par contiene elementos de cada rama funcional y, por lo tanto, puede operar de
forma independiente hasta cierto punto. Por ejemplo, un par que comparte música puede proporcionar sus archivos
almacenados localmente al usuario local sin conexión a ningún otro par. Una vez que los pares están conectados, cada uno
puede compartir los datos que tienen los demás.

U D U D Clave
U: interfaz de usuario
B — Lógica empresarial
D: acceso a los datos
B B

Compañero 1 Compañero 2

FIGURA 5.14

Aplicaciones de igual a igual representadas como un híbrido de arquitectura de un solo nivel y de dos niveles.
304 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

la red la red

U B D
Clave
U: interfaz de usuario
B — Lógica empresarial
D: acceso a los datos

Nivel de front-end Nivel medio Nivel de acceso a datos


(lógica de negocios)

FIGURA 5.15

Una aplicación idealizada de tres niveles.

5.6.3 APLICACIONES DE TRES NIVELES


Las aplicaciones de tres niveles dividen las principales líneas de funcionalidad en tres tipos de componentes. Un objetivo
general de esta arquitectura es separar cada hebra principal de funcionalidad en su propio nivel; ver Figura 5.15 . Las
ventajas potenciales de dividirse en tres niveles incluyen el rendimiento y la escalabilidad (porque la carga de trabajo se
puede distribuir en diferentes plataformas y la replicación se puede introducir en el nivel medio y / o en el nivel de acceso a
datos según sea necesario), así como una mejor capacidad de mantenimiento y extensibilidad (porque , si las interfaces
entre niveles están bien diseñadas, se puede agregar funcionalidad en un nivel sin tener que rediseñar los otros niveles).

Figura 5.15 ilustra una aplicación idealizada de tres niveles en la que cada uno de los tres hilos funcionales se
implementa en un componente separado para mejorar la escalabilidad y el rendimiento. En realidad, la separación
de las hebras funcionales rara vez es tan limpia, y habrá una cierta dispersión de las hebras funcionales entre los
componentes. Por ejemplo, puede haber alguna lógica de acceso a los datos y / o almacenamiento de datos en el
nivel intermedio, o puede haber algún aspecto de la lógica empresarial que se implemente en los niveles de acceso
a los datos o en el front-end porque puede ser más eficiente o eficaz. , dependiendo de los requisitos reales de la
aplicación.

5.6.4 APLICACIONES MULTITIER


Muchas aplicaciones tienen una amplia funcionalidad y requieren el uso de varios servicios adicionales
más allá de la función empresarial subyacente. Por ejemplo, una aplicación bancaria puede necesitar
una funcionalidad asociada con la seguridad y autenticación (de usuarios y sistemas conectados),
tasas de interés, tipos de cambio de divisas, transferencias de fondos entre cuentas internas y hacia /
desde cuentas externas, cálculo de tarifas y cargos, y muchos otros, además de las operaciones
básicas de administración de fondos dentro de una cuenta bancaria. Estos sistemas funcionalmente
diversos no se pueden construir de manera efectiva utilizando enfoques de dos o tres niveles. Para
gestionar la complejidad del propio sistema y asegurar su extensibilidad, así como para asegurar la
mantenibilidad de los subcomponentes, estos sistemas necesitan potencialmente muchos tipos de
componentes,
Figura 5.16 ilustra el concepto de diseño de varios niveles. Se aplican las mismas ideas básicas del diseño de tres niveles,
pero la funcionalidad se extiende a más tipos de componentes para proporcionar un diseño modular y, por lo tanto, más
escalable y extensible. Una de las principales motivaciones de este enfoque es gestionar (limitar) la complejidad de
5.7 SERVIDOR DE CLIENTE 305

B D

U
B

Clave
B D D
U: interfaz de usuario
B — Lógica empresarial
D: acceso a los datos

FIGURA 5.16

Un ejemplo de distribución funcional en una aplicación de varios niveles.

cada tipo de componente y para lograr flexibilidad en la forma en que los componentes se utilizan y se conectan. Por
ejemplo, puede haber algunas funciones específicas que no sean necesarias en todas las instalaciones del software; Si el
mapeo de la funcionalidad a los componentes se realiza de manera apropiada, entonces los componentes relevantes se
pueden omitir en algunas implementaciones. El enfoque modular también facilita la actualización de componentes
individuales sin interrumpir otros.

5.7 SERVIDOR DE CLIENTE


La CS es quizás el modelo más conocido de computación distribuida. Este es un modelo de dos niveles en el que las
tres principales líneas de funcionalidad se dividen en dos tipos de componentes.
Una instanciación en ejecución de una aplicación CS comprende al menos dos componentes: al menos un
cliente y al menos un servidor. La lógica empresarial de la aplicación se divide en estos componentes que tienen
roles definidos e interactúan de forma precoreografiada en varios grados en diferentes aplicaciones. La interacción
está definida por el protocolo de nivel de aplicación, por lo que para un ejemplo muy simple, el cliente puede
solicitar una conexión, enviar un mensaje de solicitud (de servicio), recibir una respuesta del servidor y luego cerrar
la conexión. Los protocolos de nivel de aplicación se analizan en el Capítulo 3.

5.7.1 VIDA ÚTIL DEL CLIENTE Y SERVIDOR


En la mayoría de las aplicaciones de CS, el servidor se ejecuta continuamente y el cliente se conecta cuando es necesario.
Esta disposición refleja la típica necesidad empresarial subyacente: que el servidor debe estar siempre disponible porque no
es posible saber cuándo los usuarios humanos necesitarán servicio y, por lo tanto, ejecutarán el cliente. Básicamente, el
usuario espera un servicio bajo demanda. Sin embargo, el usuario no tiene control sobre el servidor y los clientes no pueden
hacer que el servidor se inicie bajo demanda. El cliente generalmente se apaga una vez que finaliza la sesión del usuario.
306 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

No es deseable dejar los componentes del cliente ejecutándose continuamente por varias razones que incluyen
las siguientes:

1. Utilizaría recursos mientras esté activo incluso cuando no se realicen solicitudes, y no hay
certeza de que se realicen más solicitudes.
2. Mantener a los clientes en funcionamiento requiere que sus equipos host también se mantengan en funcionamiento, incluso
cuando sus propietarios no los necesiten.
3. Muchas aplicaciones relacionadas con negocios involucran a clientes que manejan información privada del usuario o
secreta de la compañía y generalmente requieren alguna forma de autenticación de usuario (los ejemplos incluyen
aplicaciones bancarias, de comercio electrónico y de correo electrónico); por lo tanto, incluso si el componente del
cliente sigue ejecutándose, la sesión del usuario debe finalizar (y, por lo general, eso también finaliza la conexión con el
servidor). Un nuevo usuario tendría que ser autenticado y establecer una nueva conexión con el servidor, por lo que
aún incurriría en una gran fracción de la latencia total incurrida al reiniciar el componente desde cero.

5.7.2 LADOS ACTIVOS Y PASIVOS DE LA CONEXIÓN


El componente que inicia una conexión se describe como el lado activo y el componente que espera las
solicitudes de conexión se describe como el lado pasivo. (Piense en entablar una conversación con alguien
de forma activa, en lugar de ser abordado por otra persona que inicie una conversación con usted. No tiene
que hacer nada inicialmente excepto estar allí; por lo tanto, su comportamiento es pasivo).
La conexión del cliente a los servicios a pedido está respaldada por dos características principales de la forma en que los
servidores suelen operar: en primer lugar, el hecho de que los servidores tienden a estar continuamente disponibles (como se
mencionó anteriormente) y, en segundo lugar, porque tienden a estar vinculados a conocidos puertos y pueden direccionarse
mediante URL fijas (es decir, pueden ubicarse mediante un servicio como DNS; consulte la discusión detallada en el Capítulo 6).

5.7.3 EL MODELO ARQUITECTÓNICO DE CS


CS es una arquitectura lógica; no especifica las ubicaciones físicas relativas de los componentes, por lo que pueden
estar tanto en la misma computadora como en diferentes computadoras. Cada componente se ejecuta como un
proceso; por lo tanto, la comunicación entre ellos se encuentra en la capa de transporte (y superior) y puede
basarse en el uso de sockets, los protocolos TCP o UDP y la comunicación de nivel superior.
Figura 5.17 ilustra la arquitectura CS general, en una situación en la que dos procesos cliente están
conectados a un solo servidor. Es bastante común que un servidor permita conectar muchos clientes

Servidor
Proceso
S
Cliente Cliente
Conexión1 Conexión2
Proceso Proceso
A B

FIGURA 5.17

Representación generalizada cliente-servidor.


5.7 SERVIDOR DE CLIENTE 307

al mismo tiempo, dependiendo de la naturaleza de la aplicación, pero la comunicación es privada entre el


servidor y cada cliente.
CS se llama así porque normalmente el servidor proporciona algún tipo de servicio a los clientes. La
comunicación generalmente la inicia el cliente, ya que el servidor no puede predecir cuándo un cliente requerirá
servicio. Por lo general, los clientes no interactúan entre sí directamente como parte de la aplicación CS, y cualquier
comunicación que se produzca entre ellos se realiza a través del servidor. En muchas aplicaciones, los clientes
individuales desconocen la presencia del otro; de hecho, este es un requisito de diseño clave para una amplia
variedad de aplicaciones, como banca en línea, comercio de acciones y servicios de difusión de medios.

En tales aplicaciones, el modelo de negocio se basa en una relación cliente-servidor privada, que opera un protocolo de
respuesta de solicitud en el que el servidor responde a las solicitudes del cliente. El hecho de que pueda haber muchos
clientes conectados simultáneamente al servidor debe ocultarse por completo a los propios clientes; este es el requisito de
transparencia de concurrencia en el nivel de arquitectura superior. Sin embargo, se podría sentir un efecto en el
rendimiento de otros clientes si la carga de trabajo en el servidor es lo suficientemente alta como para que los clientes
hagan cola para recibir servicio en una escala de tiempo que los usuarios noten (esto depende en gran medida de la
aplicación). Las técnicas para garantizar que los servicios sigan respondiendo a medida que aumenta la carga y la escala
incluyen la replicación de servidores, que se analiza en profundidad en este capítulo y también se analiza desde una
perspectiva de transparencia en el Capítulo 6.
Se puede decir que los clientes en tales aplicaciones están aislados entre sí con respecto al acoplamiento,
y son independientes entre sí en términos de su lógica y función de negocio. Cada uno de los clientes está
acoplado con el servidor, ya sea de forma flexible o estrecha, según el diseño del protocolo de nivel de
aplicación y la forma en que los componentes se asignan entre sí.
Por el contrario, un juego multijugador de CS es un buen ejemplo de una aplicación en la que los clientes están conectados
lógicamente a través del juego (su lógica de negocio) y, por lo tanto, son necesariamente conscientes entre sí e interactúan, pero
indirectamente a través del servidor (es decir, los clientes están indirectamente acoplados entre sí como se discutió anteriormente).
En una aplicación de este tipo, es probable que el servidor gestione los recursos compartidos, como el estado del juego, y controle el
flujo del juego, especialmente en los juegos por turnos. En este caso, la arquitectura se ajusta a la variante de servidor pesado de CS;
vea la siguiente sección.
Para las aplicaciones interactivas, el cliente suele estar asociado con usuarios humanos (actúa como su agente). Por ejemplo, un
cliente de correo electrónico se conecta a un servicio de correo electrónico remoto. El cliente proporciona una interfaz a través de la
cual el usuario puede solicitar que se recuperen mensajes de correo electrónico del servidor o puede enviar mensajes al servidor para
que se envíen como correos electrónicos a otros usuarios.
Figura 5.18 ilustra una configuración típica de correo electrónico y un escenario de uso. Al mantener la bandeja de entrada del correo

electrónico de forma centralizada en una ubicación conocida (que se identifica por la parte del dominio de la dirección URL de la dirección de

correo electrónico del usuario), un usuario puede acceder a su correo electrónico desde cualquier lugar en el que tenga una conexión de red. El

usuario puede acceder al servidor utilizando uno de varios programas de cliente de correo electrónico que se ejecutan en diferentes dispositivos.

La interfaz de usuario y la presentación de datos pueden ser diferentes en cada caso, pero los datos reales serán los mismos. Los destinatarios

del correo electrónico no podrán determinar qué dispositivo o cliente de correo electrónico se utilizó para crear el correo electrónico, ya que el

servidor de correo electrónico envía todos los correos electrónicos.

Los servidores de aplicaciones a menudo se alojan en computadoras dedicadas que están configuradas especialmente
para este propósito (por ejemplo, puede tener una memoria más grande y una CPU más rápida para garantizar que pueda
manejar solicitudes a alta velocidad y con poca demora). En tales casos, a veces se hace referencia a la computadora como
servidor, pero de hecho, es el proceso que se ejecuta en la computadora, que en realidad es el servidor.
308 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Envío / recepción de correo electrónico externo


El usuario usa una computadora de escritorio
Correo electrónico
para comprobar si hay nuevos mensajes de correo
cliente
electrónico. Esta computadora tiene un determinado cliente

de correo electrónico instalado #1 1.

(a) 2.

Correo electrónico De Fecha Mensaje


Stephen 04/06/2013 Le escribo para preguntar sobre ...
Mary 06/06/2013 ¿Podrías consultar el
servidor Annie 06/06/2013 Vuelva a enviar el archivo adjunto.
Anisha 06/07/2013 Tengo buenas noticias que contarte ...
Schmidt 06/09/2013 El comité quisiera preguntar ...

3. Bandeja de entrada del correo electrónico del usuario

B. Posteriormente, el mismo usuario usa un


4.
dispositivo móvil como una tableta para redactar y Correo electrónico
enviar un mensaje de correo electrónico. La tableta cliente
tiene un cliente de correo electrónico diferente
#2
instalado

(B)
Clave

1. El usuario ve el correo electrónico (el cliente solicita el contenido de la bandeja de entrada del servidor)

2. El servidor envía una respuesta que contiene mensajes de correo electrónico desde la bandeja de entrada.

3. El usuario crea el correo electrónico y lo 'envía' (el cliente pasa el mensaje de correo electrónico al servidor, que en realidad lo envía)
4. El servidor envía la confirmación de que se envió el correo electrónico (algunos clientes pueden mostrarlo y otros no)

FIGURA 5.18

Un ejemplo de aplicación de correo electrónico de configuración cliente-servidor.

5.7.4 VARIANTES DEL MODELO CS


Como se discutió anteriormente, hay tres líneas principales de funcionalidad en las aplicaciones distribuidas, relacionadas
con la interfaz de usuario, la lógica empresarial y el acceso y el mantenimiento de los datos, respectivamente. Surgen varias
variantes arquitectónicas de CS, basadas en diferentes distribuciones de estos hilos funcionales sobre los componentes de
cliente y servidor.
Como sugieren los nombres, fat server (también conocido como thin client) describe una configuración en la que la
mayor parte del trabajo se realiza en el servidor, mientras que en fat client (también conocido como thin server), la mayor
parte del trabajo se realiza en el cliente. . Las variantes equilibradas son aquellas en las que el trabajo se comparte de
manera más uniforme entre los componentes (estas variaciones se ilustraron en Figura 5.13 ). Incluso dentro de estas
categorías amplias, hay varias formas en que se distribuyen las hebras reales de funcionalidad, por ejemplo, el cliente puede
tener alguna información del estado local, y el resto se administra en el servidor. En tal caso, esto debe diseñarse de manera
que los clientes mantengan solo el subconjunto de estado que es específico de los clientes individuales y el servidor tenga
un estado compartido.
Las configuraciones de servidor gordo tienen ventajas en términos de accesibilidad a los datos compartidos (toda la lógica y los
datos de acceso a los datos se mantienen en una ubicación central), seguridad (la lógica empresarial se concentra en el lado del
servidor y, por lo tanto, está protegida contra modificaciones no autorizadas, y todos los accesos a datos filtrarse en función de la
autorización) y la capacidad de actualización (las actualizaciones de la lógica empresarial solo deben aplicarse a la pequeña cantidad
de componentes del servidor y, por lo tanto, son potencialmente mucho más simples que cuando es necesario actualizar una gran
cantidad de clientes implementados).
Las configuraciones de clientes pesados son apropiadas cuando muchos de los datos son locales para los usuarios individuales y
no requieren compartirlos con otros clientes. El diseño de cliente pesado también es ideal en situaciones en las que la lógica
empresarial se personaliza de alguna manera para usuarios individuales (esto podría ser relevante, por ejemplo, en algunos juegos y
aplicaciones empresariales como el comercio de acciones). Una ventaja importante del enfoque de cliente gordo es la escalabilidad. El
cliente hace gran parte del trabajo, de modo que el servidor es, por implicación, "delgado" (hace menos trabajo por cliente) y, por lo
tanto, puede admitir más clientes, ya que el costo incremental de agregar clientes es relativamente bajo.
5.7 SERVIDOR DE CLIENTE 309

Las aplicaciones CS que distribuyen la lógica empresarial y las funciones de acceso a datos entre los componentes del
cliente y del servidor pueden describirse como configuraciones equilibradas. En dichas aplicaciones, hay dos categorías de
datos: los que solo usan los clientes individuales, como los datos personales, los datos históricos de uso, las preferencias y
los ajustes de configuración, y los que se comparten entre todos o muchos de los clientes y, por lo tanto, deben se llevará a
cabo de forma centralizada. La lógica empresarial también se puede dividir en los tipos de dos componentes, de modo que
el procesamiento que es local para el cliente y no requiere acceso a los datos compartidos se realiza en el host del cliente
(por ejemplo, para permitir la personalización del comportamiento o para agregar opciones especializadas relacionadas a
las preferencias o necesidades del cliente en particular o del usuario relacionado). Esto también tiene la ventaja de reducir la
carga en el host del servidor, hacer que el servicio sea más receptivo y mejorar la escalabilidad. Sin embargo, la lógica
empresarial central que manipula los datos compartidos y / o se espera que esté sujeta a cambios futuros se ejecuta en el
lado del servidor para mejorar la eficiencia y facilitar el mantenimiento y las actualizaciones. La configuración equilibrada
representa un compromiso entre las ventajas de flexibilidad del enfoque de cliente gordo y las ventajas del almacenamiento
y la gestión de datos centralizados (por seguridad y coherencia) del servidor gordo.

5.7.5 SERVICIOS ESTATALES VERSUS APÁTRIDAS


En algunos casos, el cliente puede contener toda la información del estado de la aplicación y el servidor no;
simplemente responde a la solicitud de cada cliente sin guardar ningún detalle del historial de transacciones. Por
tanto, esta clase de servicio se denomina apátrida; ver Figura 5.19 .
Figura 5.19 proporciona una comparación de servicios con estado, en la que el proceso del servidor realiza un
seguimiento del estado de la aplicación, con los servicios sin estado, en la que el servidor trata cada nueva solicitud de
cliente de forma independiente de todas las demás y no conserva la información de estado sobre la actividad actual de la
aplicación. El enfoque sin estado es muy poderoso para lograr robustez, especialmente en sistemas de gran escala. Esto se
debe principalmente a que la falla de un servidor con estado interrumpe las actividades de todos los clientes conectados y
requiere que se recupere el estado para garantizar la coherencia continua cuando se reinicia el servidor, mientras que la
falla de un servidor sin estado no pierde ninguna información de estado. Cuando falla un servidor sin estado, sus clientes
pueden conectarse a una nueva instancia del servidor sin la necesidad de ninguna recuperación de estado (porque cada
cliente mantiene el estado de su propia sesión de aplicación, localmente). Otra forma en la que se mejora la robustez con el
enfoque de servidor sin estado es que conduce a una menor complejidad en los componentes del servidor, lo que los hace
más fáciles de desarrollar y probar. El juego multijugador de caso de uso proporciona un ejemplo de un diseño de servidor
con estado; el servidor almacena el estado del juego, como el turno de qué jugador debe realizar un movimiento.

Abrir documento Abrir documento

Solicitar primer registro Solicitar ID de registro = 1

Solicitar siguiente registro Solicitar ID de registro = 2

Solicitar siguiente registro Solicitar ID de registro = 3

Cerrar el archivo Cerrar archivo

Servicio con estado Servicio sin estado


El proceso del servidor realiza un seguimiento del estado de la sesión de la El servidor no conserva ningún estado relacionado con la sesión de la aplicación,
aplicación (en este ejemplo, el número de registro actual al que se accede) cada solicitud del cliente se trata de forma aislada de las demás.

FIGURA 5.19

Servicios con estado versus sin estado.


310 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

5.7.6 SISTEMAS CS MODULARES Y JERÁRQUICOS


Tener solo tipos de dos componentes puede ser una limitación en algunas situaciones. Puede ser necesario dividir la
funcionalidad de un servicio en varios subcomponentes para garantizar un diseño eficaz y limitar la complejidad de un solo
componente. Dicha distribución también tiende a mejorar la solidez, la capacidad de mantenimiento y la escalabilidad.
Considere la situación en la que una empresa tiene su propio sistema de autenticación interno, que está destinado a validar
todas las solicitudes de servicio en varias aplicaciones diferentes. Hay tres aplicaciones CS diferentes que se utilizan para
proporcionar los servicios necesarios para el negocio de la empresa, y cada usuario tiene un único conjunto de credenciales
de acceso para utilizar los tres servicios.
Una opción sería integrar el sistema de autenticación en cada uno de los servicios comerciales, de modo que
cuando llegue cualquier solicitud de un cliente (en cualquiera de los servidores), ocurrirá la misma actividad de
autenticación. Este enfoque no es deseable porque requiere que las tres aplicaciones se rediseñen y que los
componentes del servidor crezcan en términos de complejidad, tamaño de código real y requisitos de recursos en
tiempo de ejecución. La lógica de autenticación debe duplicarse en los tres servicios y esto cuesta un mayor
esfuerzo de diseño, desarrollo y prueba. Este enfoque también significa que cualquier actualización futura del
sistema de autenticación debe realizarse en las tres copias; de lo contrario, habrá diferencias en el comportamiento
y la fuerza de la autenticación puede volverse inconsistente.
Una mejor opción desde un punto de vista arquitectónico sería desarrollar el sistema de autenticación como un
servicio separado (supongamos que el modelo CS es apropiado para el propósito del ejemplo). El lado del servidor
del sistema de autenticación realmente realizará las comprobaciones de autenticación, lo que implicará comparar
las credenciales proporcionadas por los clientes con los datos que posee el servicio para determinar quién tiene los
derechos para realizar diversas acciones o acceder a los recursos de datos. El lado del cliente del servicio de
autenticación puede ser "delgado" (consulte la discusión anterior), de modo que sea adecuado para la integración
en otros servicios sin agregar mucha complejidad. De este modo, el cliente de autenticación puede integrarse en los
tres servicios comerciales que utiliza la empresa,

Para ilustrar este escenario de servicio jerárquico, se presenta un ejemplo de aplicación específico: considere una
aplicación que comprende dos niveles de servicio (acceso a la base de datos y servicio de autenticación). El sistema está
construido con tres tipos de componentes: el servidor de la base de datos (que consta de la base de datos en sí y la lógica
empresarial necesaria para acceder y actualizar los datos), el cliente de la base de datos (que proporciona la interfaz local de
usuario para acceder a la base de datos), y un servidor de autenticación (que contiene la información necesaria para
autenticar a los usuarios de la base de datos). Tenga en cuenta que el servidor de la base de datos debe desempeñar el
papel de cliente del servicio de autenticación, ya que realiza solicitudes para que sus usuarios se autentiquen. Esto
proporciona un ejemplo en el que un solo componente cambia entre los roles de cliente y servidor de forma dinámica o
desempeña ambos roles simultáneamente. 1 dependiendo de los detalles más finos del diseño de comportamiento. Este
ejemplo se ilustra en Figura 5.20 .
Figura 5.20 ilustra un enfoque modular de los servicios en el que un servidor de base de datos realiza solicitudes de servicio a un servicio de

autenticación independiente. Ambos servicios se implementan utilizando el modelo CS y la funcionalidad de autenticación del lado del cliente

está integrada en el componente del servidor de la base de datos. De esta forma, el servidor de la base de datos se convierte efectivamente en

un cliente del servicio de autenticación. Este enfoque tiene

1 La relación entre un vendedor en una tienda y el cliente proporciona una analogía del comportamiento humano del cambio de
función del componente. El vendedor (el servidor) atiende al cliente (que es el cliente). Sin embargo, el vendedor puede necesitar
pedir algunos productos especiales para el cliente a otro distribuidor. Por lo tanto, el rol del vendedor cambia a cliente para los
propósitos de la segunda transacción cuando el vendedor solicita bienes al proveedor externo.
5.7 SERVIDOR DE CLIENTE 311

Servicio de autenticacion
Autenticidad

catión
Servidor
Cliente de autenticación construido
en el servicio de base de datos

2. Autenticación 3. Solicitud
pedido aceptado
Aplicación de negocios

1. Acceso a la base de datos Base de datos


pedido Servidor
Cliente Cliente
Proceso 4. Resultado Proceso
A B

(a) La autenticación se realiza correctamente

Autenticidad
catión
Servidor

2. Autenticación 3. Solicitud
pedido negado

Base de datos 1. Acceso a la base de datos

Servidor pedido
Cliente Cliente
Proceso 4. Rechazado Proceso
A B

(B) La autenticación falla

FIGURA 5.20

Servicios modulares; el servicio de base de datos utiliza el servicio de autenticación.

más ventajas en términos de transparencia y seguridad. Los usuarios no necesitan acceder directamente al servicio de
autenticación; todos los accesos se realizan de forma indirecta a través de las demás aplicaciones. Esto significa que el
usuario desconoce la configuración interna y las comunicaciones que se producen. En la parte A de la figura, el cliente A está
autenticado para acceder a la base de datos, mientras que en la parte B, se niega el acceso al cliente B; en ambos casos, a
los clientes les parece que el servidor de la base de datos ha realizado la verificación de autenticación él mismo.
Las arquitecturas CS pueden extenderse a situaciones en las que un cliente necesita acceso a más de un servidor,
especialmente cuando un componente de la aplicación necesita acceder a múltiples recursos remotos o compartidos. Un
ejemplo de esto es cuando los datos requeridos se distribuyen en varias bases de datos o cuando una sola base de datos se
distribuye en un sistema. El escenario en el que un solo componente necesita acceder a dos bases de datos independientes
se explora con la ayuda de Figura 5.21 en la siguiente sección.
312 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Clave
Base de datos
Proceso para procesar la conexión
servidor
Base de datos
#1
Conexión lógica empresarial

Acceso directo a la base de datos local


Solicitud
cliente

Base de datos
Acoplamiento directo. El cliente
servidor
conoce las interfaces de acceso y la
Base de datos
#2
ubicación de las bases de datos.

(a)

Solicitud Base de datos


Servidor servidor
ejemplo #1
Base de datos

#1

Solicitud
cliente

Solicitud Base de datos


Servidor
servidor
Acoplamiento indirecto. Cliente ejemplo Base de datos
#2
se conecta a dos servidores de #2

aplicaciones e indirectamente accede a


dos bases de datos, pero desconoce su
ubicación y su
interfaces de acceso Base de datos

(B) servidor
#1
Base de datos

Solicitud Solicitud
cliente Servidor

Transparencia en la distribución. Al Base de datos

cliente se le presenta la ilusión de un solo servidor


Base de datos
#2
base de datos y desconoce la
ubicación y las interfaces de acceso de
las entidades reales de la base de datos

(C)
FIGURA 5.21

Acoplamiento directo de dos niveles versus acoplamiento indirecto de tres niveles a los servicios.

5.8 ARQUITECTURAS DE TRES NIVELES Y MÚLTIPLES


CS es una forma de arquitectura de dos niveles, su principal fortaleza arquitectónica es su simplicidad. Sin embargo,
no es particularmente escalable por varias razones, que incluyen (1) la lógica de la aplicación concentrada en el tipo
de componente de servidor único (y por lo tanto la complejidad del componente aumenta aproximadamente
linealmente con la funcionalidad); (2) las limitaciones de flexibilidad y robustez que surgen de las relaciones de
comunicación directa entre el usuario del servicio y el proveedor del servicio; y (3) el cuello de botella de
rendimiento que surge porque todos los clientes se conectan a un servicio específico, que puede comprender una
única instancia de proceso.
5.8 ARQUITECTURAS DE TRES NIVELES Y MÚLTIPLES 313

La introducción de niveles adicionales, es decir, dividir la lógica de la aplicación en módulos más pequeños y distribuirla
entre más tipos de componentes, proporciona una mayor flexibilidad y escalabilidad y también puede tener otros beneficios
como solidez y seguridad. Estas arquitecturas tienen tres o más niveles y se denominan comúnmente arquitecturas de tres
niveles, pero también se utiliza el término multinivel. Tenga en cuenta que ninguno de los usos se cumple estrictamente en
términos de la cantidad real de niveles implementados.
Los beneficios de la arquitectura de tres niveles se ilustran con un ejemplo para el que es adecuada: la banca en línea.
Considere algunos de los principales requisitos de diseño para una aplicación de este tipo:

• El servicio debe ser seguro. No debe haber acceso no autorizado a los datos.
• El servicio debe ser robusto. No debe haber corrupción de datos y el sistema debe permanecer consistente en todo
momento. Los fallos de componentes individuales no deberían provocar un fallo general del sistema, y los
usuarios no deberían poder detectar dichos fallos de componentes.

• El servicio debe ser altamente escalable. Debería haber una forma sencilla de ampliar la capacidad a medida que
crece la base de clientes del banco o el conjunto de servicios ofrecidos.
• El servicio debe ser flexible. El banco debe poder cambiar o agregar funcionalidad. El
funcionamiento del sistema en sí debe cumplir con la legislación, como la protección de datos y las
leyes de privacidad, que pueden modificarse de vez en cuando.
• El servicio debe tener una alta disponibilidad. Los clientes deben poder acceder al servicio en cualquier
momento del día o de la noche (el objetivo es un servicio 24/7/365).

Aunque estos requisitos se han establecido específicamente en el contexto de un escenario de banca en línea,
resulta que en realidad son, en general, representativos de los requisitos de una gran proporción de aplicaciones
distribuidas corporativas. Se enumeran en un posible orden de prioridad para una aplicación bancaria, y este orden
no será necesariamente el mismo para otras aplicaciones. En esencia, los requisitos son seguridad, solidez,
escalabilidad, flexibilidad y disponibilidad. Manteniendo el ejemplo a un nivel bastante alto, consideremos ahora las
formas en que la arquitectura de tres niveles satisface o contribuye a cada uno de estos requisitos.

Seguridad. El cliente está desacoplado del nivel de acceso a datos por el nivel de lógica empresarial intermedia. Esto
permite que se produzca una validación sólida del usuario antes de que las solicitudes del usuario se pasen a los
componentes sensibles a la seguridad. También oscurece la arquitectura interna del sistema; un atacante puede enviar una
solicitud falsa al nivel medio, pero el sistema se puede configurar de modo que el tercer nivel solo acepte solicitudes del
nivel medio y que, cuando se vea externamente desde la red del banco, el tercer nivel no sea detectable.
Robustez. La arquitectura de tres niveles permite implementar la replicación en todos los niveles excepto en el primer nivel. Esto
se debe a que cada usuario debe tener exactamente un proceso de cliente para acceder al sistema; Puede haber muchos clientes
activos a la vez, pero esto no es una replicación, ya que cada cliente es único y está controlado de forma independiente por su
usuario. El nivel de lógica empresarial y el nivel de acceso a datos se pueden replicar, en diferentes extensiones, según sea necesario,
para garantizar que el servicio sea sólido. Es el diseño del mecanismo de replicación en el nivel de acceso a los datos lo que
contribuye de manera más significativa a garantizar la coherencia de los datos a pesar de las fallas de los componentes individuales.

Escalabilidad. La replicación tanto en la lógica empresarial como en los niveles de acceso a datos también contribuye a la
escalabilidad. Se pueden agregar instancias adicionales de los componentes para satisfacer la creciente demanda de servicios. El
segundo y tercer nivel se pueden escalar asimétricamente dependiendo de dónde ocurran los cuellos de botella. Por ejemplo, si la
validación del usuario se convierte en un punto de estrangulamiento a medida que aumenta la carga en los mecanismos de
validación, entonces la capa de lógica empresarial se puede expandir con un factor de replicación más alto que la capa de acceso a
datos, que puede continuar funcionando satisfactoriamente con su nivel actual de recurso.
314 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Flexibilidad. Recuerde que las arquitecturas de tres niveles también se denominan a veces multinivel. Esto se debe a
que no tiene que haber exactamente tres capas y el uso de terminología no siempre es preciso. Considere lo que sucedería
si no solo el mecanismo de validación del usuario se convirtiera en un cuello de botella serio debido al aumento de la carga
(como se describe en el párrafo anterior), sino que también se reforzara la legislación que rige la forma en que los bancos
realizan la validación del usuario, lo que requiere controles significativamente más estrictos en su lugar (que son, en
consecuencia, más intensivos en recursos). En tal caso, si la validación sigue siendo parte de la lógica empresarial, este tipo
de componente se volverá muy complejo y pesado. Un mejor enfoque podría ser introducir una nueva capa en el sistema y
separar la lógica de validación del usuario de la otra lógica empresarial. El enfoque de múltiples niveles permite que
cambios como este ocurran en una capa sin afectar a los otros componentes, por lo que, por ejemplo, el componente de
usuario-cliente y el componente de acceso a datos idealmente pueden permanecer sin cambios. Esto limita el costo del
cambio y quizás reduce de manera más significativa los riesgos de inestabilidad que surgen si se cambian demasiadas cosas
a la vez.
Disponibilidad. Una vez más, es la flexibilidad de poder replicar en múltiples capas lo que proporciona la base para un
servicio de alta disponibilidad. Si algunas de las réplicas están ubicadas en diferentes sitios físicos, entonces el servicio
puede incluso continuar operando a pesar de los desastres locales del sitio, como inundaciones y cortes de energía. Siempre
que esté funcionando al menos un componente de cada tipo, es posible que el servicio general sea completamente
funcional. Sin embargo, tenga en cuenta que esto debe estar sujeto a cumplir con todos los demás requisitos; por ejemplo,
el aspecto de la coherencia de los datos del requisito de robustez puede exigir que se estén ejecutando un mínimo de, por
ejemplo, tres componentes de acceso a los datos en cualquier momento.
Las arquitecturas de tres niveles tienen más ventajas sobre los diseños de dos niveles, siendo la más
importante el mayor grado de transparencia que brindan y los beneficios adicionales asociados con esto.
Se utiliza una aplicación genérica orientada a bases de datos que accede a dos bases de datos diferentes para ejemplificar los
beneficios de transparencia que surgen a través de la progresión de un diseño de dos niveles a un diseño de tres niveles; esto se
explica con la ayuda de Figura 5.21 .
Figura 5.21 ilustra los beneficios de utilizar niveles adicionales. La figura muestra tres formas posibles de conectar un
componente de la aplicación a un par de bases de datos. La parte (a) de la figura muestra una configuración de dos niveles
en la que el componente está conectado directamente a los servicios de la base de datos. En esta situación, toda la lógica
empresarial se implementa en el único componente de la aplicación (que se muestra como cliente en la figura, porque
realiza solicitudes de servicio al servicio de la base de datos). Esta configuración es un ejemplo de acoplamiento directo y
tiene la ventaja de un bajo costo de desarrollo inicial y simplicidad operativa.
Sin embargo, esta configuración carece de transparencia en varios aspectos importantes. Esta configuración requiere
que el desarrollador de la aplicación del lado del cliente se ocupe de la distribución de los componentes directamente;
podemos decir que no es transparente para la distribución. El desarrollador debe tener en cuenta qué datos se encuentran
en cada base de datos al desarrollar el código de la aplicación que accede a los datos. Escenarios complejos, como lo que
debería suceder cuando solo una de las bases de datos está disponible, o si una falla en realizar una transacción pero la otra
tiene éxito (lo que puede ser especialmente complejo en términos de consistencia de datos), deben decidirse y los
escenarios deben detectarse y detectarse automáticamente. soportado en la lógica de la aplicación.

En términos de transparencia de ubicación y acceso, el componente cliente debe conocer o encontrar la


ubicación de los servidores de la base de datos para poder conectarse y, debido a que la conexión es directa, debe
conocer el formato nativo de la interfaz de la base de datos. Si se cambió el tipo de base de datos, es posible que el
componente del cliente deba actualizarse para tener en cuenta los cambios en la interfaz de las bases de datos,
como los formatos de mensaje utilizados y la forma en que se logra la conectividad lógica con el servidor de la base
de datos (p. Ej., la forma en que el cliente se autentica puede cambiar o ser diferente para cada una de las dos bases
de datos).
5.8 ARQUITECTURAS DE TRES NIVELES Y MÚLTIPLES 315

Parte (b) de Figura 5.21 muestra una arquitectura alternativa más sofisticada en la que se introduce un tercer nivel.
Parte de la lógica empresarial se traslada a los componentes del servidor de nivel de aplicación que manejan la conectividad
y la comunicación con los servicios de la base de datos.
Los servidores a nivel de aplicación pueden realizar funciones adicionales como seguridad y control de acceso,
brindando transparencia de acceso y ubicación al cliente: el primero en el sentido de que las bases de datos pueden
tener sus propios formatos nativos, que el servidor de aplicaciones maneja, ocultando así estos diferencias con el
cliente, y esto último porque el servidor de aplicaciones puede ocuparse de localizar el servicio de la base de datos
sin que el cliente necesite conocer su ubicación o tener el mecanismo necesario para localizarlo.
Este enfoque es superior en varios aspectos. En primer lugar, oculta al cliente la posible heterogeneidad de las bases de
datos simplificando la lógica del cliente. En segundo lugar, desacopla el componente del cliente de los componentes de la
base de datos, mejorando potencialmente la seguridad y la solidez, ya que la autenticación y el filtrado de solicitudes se
pueden agregar al nuevo nivel si es necesario y, por lo tanto, el cliente no puede manipular directamente los datos. En
tercer lugar, muchos clientes pueden utilizar potencialmente el mismo componente de servidor de aplicaciones. Esto
centraliza la lógica empresarial de la aplicación, lo que facilita el mantenimiento de la aplicación y simplifica las
actualizaciones de la lógica empresarial.
Parte (c) de Figura 5.21 muestra una arquitectura más desarrollada en la que un servidor de nivel de aplicación se ocupa
de todos los aspectos de la conectividad de la base de datos, de modo que al cliente se le presenta la ilusión de que existe
una única entidad de base de datos. Esto se logra porque el cliente solo se conecta a un único servidor de aplicaciones, que
se encarga de la conexión a las múltiples bases de datos, proporcionando al cliente una abstracción de un solo sistema. En
esta configuración, el servidor proporciona transparencia de distribución además de las otras formas de transparencia
logradas por la configuración (b).
Tenga en cuenta que la configuración (c) es un ejemplo de una aplicación de tres niveles: el cliente de la
aplicación es el primer nivel (la interfaz de usuario), el servidor de aplicaciones es el segundo nivel (la lógica
empresarial) y el servidor de la base de datos es el tercer nivel (gestionando el acceso a los datos). Sin embargo,
esta disposición de componentes también podría considerarse como dos niveles de CS en los que la lógica de la
aplicación se desarrolla como una aplicación de CS, y la base de datos se desarrolla como una aplicación de CS
autónoma y las dos se fusionan. De hecho, esta podría ser una forma útil de razonar sobre la funcionalidad
requerida de los diversos componentes durante la fase de diseño. En la arquitectura de tres niveles resultante, el
componente intermedio (el servidor de aplicaciones) asume el rol de cliente en un sistema CS y tiene el rol de
servidor en el otro; ver la parte (b) de Figura 5.22 .
Figura 5.22 ilustra algunos aspectos mecánicos de la arquitectura de tres niveles. La parte (a) de la figura
muestra una posible configuración de comunicación mediante sockets. En la configuración que se muestra, el nivel
medio se conecta al nivel de datos (el nivel de datos es el lado pasivo y el nivel medio es el lado activo que inicia la
conexión). El cliente de la aplicación se conecta al nivel medio siempre que se necesita el servicio (el cliente de la
aplicación es el lado activo y el nivel medio es el lado pasivo en este caso). La parte (b) de la figura muestra una
posible forma de construir una arquitectura de tres niveles como dos etapas de CS. Esta forma de visualizar
sistemas de tres niveles es particularmente útil cuando se considera la extensión de aplicaciones de dos niveles
existentes o durante la fase de diseño de una aplicación de tres niveles porque facilita un enfoque modular del
diseño. y, en particular, puede ayudar a obtener requisitos de diseño claros para los diversos componentes. El
detalle mecanicista mostrado en Figura 5.22 es aplicable a ambas arquitecturas (b) y (c) representadas en Figura 5.21 .
Los escenarios de bases de datos múltiples descritos anteriormente se han desarrollado como una serie de tres versiones de la
aplicación, cada una de las cuales se asigna directamente a las configuraciones ilustradas en Figura 5.21 . Actividad A1
explora el comportamiento de las tres versiones, para facilitar la comprensión de aspectos como las diferencias de
transparencia entre las configuraciones, las fortalezas y debilidades relativas de las diferentes configuraciones y los
diferentes enfoques de acoplamiento representados.
316 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

4. Solicitud de conexión del cliente de la 1. Componentes de nivel medio


aplicación enviada al nivel intermedio solicitud de conexión enviada al socket

socket de escucha del servidor de escucha de tercer nivel

SL SL
5. aceptar crea 2. aceptar crea
enchufe dedicado enchufe dedicado
para la conexión a para la conexión a

Solicitud
cliente servidor de nivel medio

Aplicación S
SC SC
Nivel de datos
Servidor S
Cliente Servidor
(nivel medio)
6. Comunicación entre 3. La comunicación entre los componentes
el cliente y el servidor se producen en de nivel medio y tercero se produce en
una conexión TCP dedicada una conexión TCP dedicada

(a) Arquitectura de tres niveles: vista a nivel de socket

Cliente Servidor Cliente Servidor

(B) Arquitectura de tres niveles modelada como dos etapas cliente-servidor

Clave

Proceso Enchufe

FIGURA 5.22

La arquitectura de tres niveles; algunos aspectos mecanicistas.

Los componentes de las tres aplicaciones se comunican a través de conexiones TCP, configuradas de la misma manera
que se muestra en la parte (a) de Figura 5.22 .
Puede haber muchas razones por las que los datos se distribuyen dentro de un sistema. Los datos se pueden almacenar en una
variedad de lugares según, por ejemplo, el tipo de datos o la propiedad de los datos o la sensibilidad de seguridad de los datos. Se
puede dividir a propósito en diferentes servidores para reducir la carga en cada servidor, mejorando así el rendimiento. También se
puede replicar, de modo que haya varias copias de los mismos datos disponibles en el sistema. La distribución de datos utilizando
diferentes bases de datos físicas también puede ser una preferencia de diseño para garantizar la mantenibilidad y gestionar la
complejidad. Por ejemplo, es muy probable que una empresa minorista tenga una estructura de información que separe los detalles
del cliente en una base de datos de clientes, los detalles de las existencias en una base de datos de existencias y el personal, y los
detalles de la nómina en una base de datos adicional.
Para cualquier sistema grande, es mucho más probable que los datos se distribuyan que no. En general, sería
indeseable que una organización grande recopilara todos sus datos sobre clientes, proveedores, productos, etc., en una sola
base de datos, lo cual sería complejo y difícil de manejar, posiblemente requiera una gran cantidad de almacenamiento
localizado y probablemente sea un cuello de botella en el rendimiento porque todas las consultas de datos se pasarían al
mismo servidor. Además, muchas aplicaciones de comercio electrónico operan en varias organizaciones y es muy poco
probable que permitan que sus datos se almacenen de forma remota en el sitio de la otra organización. Lo más probable es
que cada organización divida sus datos en dos categorías: que estén felices de permitir que las organizaciones remotas
accedan a través de una aplicación distribuida de comercio electrónico y que deseen mantener la privacidad.
Por lo tanto, los diseñadores de aplicaciones distribuidas se enfrentan al desafío de acceder a
múltiples bases de datos (y otros recursos) desde una aplicación específica, de modo que los usuarios
del sistema desconocen la verdadera ubicación de los datos (u otros recursos) y no tienen preocuparse
por la complejidad de la configuración física de los sistemas subyacentes. Esta es una muy útil
5.8 ARQUITECTURAS DE TRES NIVELES Y MÚLTIPLES 317

ACTIVIDAD A1 EXPLORANDO ARQUITECTURAS DE DOS Y TRES NIVELES


Se utilizan tres versiones estructuradas de forma diferente de la misma aplicación para explorar varios aspectos importantes de las
arquitecturas de software.
Cada una de las aplicaciones accede a dos servidores de bases de datos remotos diferentes. Para simplificar la configuración del software y
asegurar que el foco de la experimentación esté en los aspectos arquitectónicos (y no en la instalación y configuración de bases de datos), los
programas del servidor de bases de datos usados en la actividad realmente contienen sus datos en forma de información. tablas de datos de
memoria en lugar de bases de datos reales. Esto no afecta los aspectos arquitectónicos, de comunicación y conectividad de su comportamiento.

Prerrequisitos
Copie los materiales de apoyo requeridos por esta actividad en su computadora; consulte la Actividad I1 en el Capítulo 1.

Los resultados del aprendizaje


Comprender las diferentes configuraciones de CS
Obtener una apreciación de la naturaleza distribuida de los recursos en la mayoría de los sistemas.

Comprender el diseño robusto en el que algunos servicios pueden estar ausentes, pero el resto del sistema aún ofrece una
funcionalidad parcial.
Comprender las diferencias entre las arquitecturas de dos y tres niveles Obtener una
apreciación de los diferentes enfoques de acoplamiento
Para explorar la transparencia de acceso en una configuración de aplicación práctica

Para explorar la transparencia de ubicación en una configuración de aplicación práctica

Explorar la transparencia de la distribución en un entorno de aplicación práctica La


actividad se lleva a cabo en tres etapas principales.

Método Parte A: Comprensión del concepto de datos distribuidos


La primera parte utiliza una implementación de dos niveles que comprende los siguientes componentes de software:
DB_Arch_DBServer_DB1_ Direct (esta es la implementación del primero de los dos servidores de base de datos y se usa durante toda la
actividad), DB_ Arch_DBServer_DB2_Direct (esta es la implementación de la segunda servidor y también se utiliza durante toda la actividad),
y DB_Arch_AppClient (esta versión del cliente se conecta directamente a cada uno de los dos servidores de base de datos). Esta
configuración corresponde a la parte (a) de Figura 5.21 .
Los datos que necesita el cliente se dividen entre los dos servidores de base de datos, de modo que cada uno pueda proporcionar una parte específica de ellos

independientemente del otro. Un servidor de base de datos contiene los detalles del nombre del cliente; el otro contiene los detalles del saldo de la cuenta del

cliente. Por lo tanto, el cliente único necesita conectarse a ambos servidores para recuperar todos los datos relevantes para un cliente en particular, pero puede
recuperar datos parciales si solo uno de los servidores está disponible.

Esta parte de la actividad demuestra la conexión directa entre el cliente de la aplicación y los servidores de la base de datos. El
cliente debe conocer la ubicación (dirección y puerto) de los servidores de la base de datos. En la aplicación de demostración, los
números de puerto se han codificado de forma rígida y se supone que la dirección IP de cada servidor es la misma que la del cliente; el
usuario debe ingresar la dirección IP correcta si el servidor está ubicado en una computadora diferente.
La conectividad y el comportamiento se pueden explorar en tres subpasos. Parte
A1. Ejecute el cliente con un solo servidor de base de datos.
Comience ejecutando el cliente (DB_Arch_AppClient) y el primero de los dos servidores de base de datos (DB_Arch_DBServer_
DB1_Direct) en la misma computadora. Intente conectar el cliente a cada servidor. Esto debería tener éxito para el primer servidor de
base de datos y fallar para el segundo. Dado que cada conexión es administrada por separado por el cliente en este diseño particular,
la ausencia de un servidor no interfiere con la conectividad con el otro.
Ahora solicita algunos datos. Proporcione un número de identificación de cliente del conjunto admitido {101, 102, 103} y haga clic en el botón
"solicitar datos". Debería ver que se recuperan los datos parciales retenidos por el servidor en particular que se está ejecutando. La aplicación está
diseñada para enviar la misma solicitud (es decir, la clave es el ID del cliente) a todos los servidores de bases de datos conectados, por lo que el hecho
de que uno de los servidores no esté disponible no impide que el otro devuelva su resultado, es decir, solo el El nombre del cliente se devuelve al
cliente.
Parte A2. Ejecute el cliente con el otro servidor de base de datos.
Confirme que ese comportamiento es simétrico con respecto a cualquiera de las bases de datos que no esté disponible. Esta vez, ejecute el
cliente (DB_Arch_AppClient) y el segundo de los dos servidores de base de datos (DB_Arch_DBServer_DB2_Direct) en la misma computadora. Siga los
mismos pasos que antes. Una vez que se haya conectado y se haya enviado una solicitud de datos del cliente,
318 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A1 EXPLORANDO ARQUITECTURAS DE DOS Y TRES NIVELES — Cont.


la base de datos debe devolver los datos apropiados de la cuenta del cliente, aunque la base de datos n. ° 1 no esté disponible para proporcionar el nombre del

cliente.

Parte A3. Ejecute el cliente con ambos servidores de base de datos.

Ahora ejecute el cliente y ambos servidores de base de datos en la misma computadora. Conecte el cliente a cada servidor de base de datos y luego envíe una

solicitud de datos. Tenga en cuenta que, en este caso, la solicitud se envía a ambos servidores de base de datos y que ambos responden con los datos que tienen,
según la clave de identificación del cliente en el mensaje de solicitud.

Es posible que pueda notar la demora entre los dos campos de datos que se actualizan en el cliente, lo que surge porque los datos
llegan en dos mensajes, desde dos servidores de bases de datos diferentes.

Resultado esperado para la Parte A


Debería ver que la aplicación distribuida funciona correctamente y que su comportamiento se corresponde con lo esperado según el
procedimiento descrito anteriormente.
Debería ver cómo el cliente configura y administra las conexiones a las dos bases de datos por separado.
Utilice los registros de eventos de diagnóstico proporcionados en los componentes del servidor de la base de datos para ver los detalles de las conexiones que

se establecen y los mensajes que se pasan entre el cliente y los servidores. Asegúrese de comprender el comportamiento que se produce.

Las capturas de pantalla a continuación muestran el comportamiento resultante cuando los tres componentes interactúan correctamente, para la parte A3 de la

actividad.
5.8 ARQUITECTURAS DE TRES NIVELES Y MÚLTIPLES 319

ACTIVIDAD A1 EXPLORANDO ARQUITECTURAS DE DOS Y TRES NIVELES — Cont.


Método Parte B: Ampliación a tres niveles
Esta parte de la actividad está relacionada con la introducción de un nivel intermedio para desacoplar el cliente de la aplicación de los servidores de
la base de datos (que estaban conectados directamente al cliente en la configuración utilizada en la parte A).
Esta segunda parte de la actividad presenta un par de servidores de aplicaciones que se ocupan de la conexión a uno de los servidores
de la base de datos. Esta configuración comprende los siguientes cinco componentes de software: DB_Arch_ DBServer_DB1_Direct (la
implementación del primero de los dos servidores de base de datos), DB_Arch_DBServer_DB2_ Direct (la implementación del segundo de
los dos servidores de base de datos), DB_Arch_AppServer_for_DB1 (el nivel intermedio que se conecta a la primera base de datos type),
DB_Arch_AppServer_for_DB2 (el nivel medio que se conecta al segundo tipo de base de datos) y DB_Arch_AppClient_for_AppServer1and2
(un componente de cliente modificado que se conecta a los nuevos servidores de aplicaciones de nivel medio en lugar de conectarse
directamente a los servidores de base de datos). Esta configuración corresponde a la parte (b) de Figura 5.21 .

La diferencia importante con la configuración de la parte A es que ahora el cliente solo conoce sus servidores de aplicaciones. Todavía tiene que
conectarse a otros dos componentes, pero ahora está acoplado indirectamente al nivel de acceso a datos y no necesita saber cómo está organizado
ese nivel (en la configuración utilizada en la parte A, estaba acoplado directamente).
La conectividad y el comportamiento se exploran en tres subpasos.
Parte B1. Ejecute el cliente, el servidor de aplicaciones que se conecta a DB1 y el servidor de base de datos DB1. Solicite datos para
uno de los ID de cliente y observe el resultado. Observe que el cliente aún administra sus conexiones por separado y, por lo tanto, se
pueden recibir datos de DB1 en ausencia de la otra base de datos.
Parte B2. Ahora, ejecute el cliente con el otro servidor de aplicaciones (que se conecta a DB2) y el servidor de base de datos DB2.
Confirme que el comportamiento del cliente es simétrico con respecto a los componentes no disponibles y que se pueden recibir datos de
DB2 en ausencia de DB1.
Parte B3. Ejecute los cinco componentes de manera que funcione el sistema completo de tres niveles. Conecte cada servidor de aplicaciones a
su respectivo servidor de base de datos, conecte el cliente a los servidores de aplicaciones y luego envíe una solicitud de datos. Tenga en cuenta
que la solicitud se envía por separado a cada servidor de aplicaciones, que luego la reenvía a su servidor de base de datos. Tenga en cuenta
también que las respuestas de los servidores de la base de datos se envían al cliente, que muestra los datos resultantes.
Al igual que con la parte A3, es posible que también pueda notar el retraso entre los dos campos de datos que se actualizan en
el cliente. Puede ser un poco más obvio en este caso, ya que los dos conjuntos de mensajes tienen que pasar a través de cadenas de componentes más
largas, lo que aumenta la latencia.

Resultado esperado para la Parte B


Al experimentar con esta configuración, debería poder ver algunas de las diferencias que surgen como resultado de que se trata de una
aplicación de tres niveles, en la que el cliente de la aplicación es el primer nivel (interfaz de usuario), el servidor de aplicaciones es el
segundo nivel (lógica empresarial) y el servidor de la base de datos es el tercer nivel (acceso a datos).
Utilice los registros de eventos de diagnóstico proporcionados en los componentes del servidor de aplicaciones y los componentes del servidor
de base de datos para ver los detalles de las conexiones que se establecen y los mensajes que se pasan entre los tres niveles. Asegúrese de
comprender el comportamiento que se produce.
Los servidores de aplicaciones rompen el acoplamiento directo que se utilizó en la arquitectura de dos niveles. Los servidores de aplicaciones
brindan transparencia en la ubicación y el acceso. La transparencia de la ubicación se logra porque los servidores de aplicaciones se conectan a los
servidores de la base de datos de manera que el cliente no necesita conocer los detalles de ubicación de ellos y ni siquiera necesita saber que los
servidores de la base de datos son componentes externos. La transparencia del acceso se logra porque los servidores de aplicaciones ocultan la
heterogeneidad de las dos bases de datos, haciendo que toda la comunicación con el cliente sea homogénea, utilizando un protocolo de
comunicación específico de la aplicación consistente.
También es importante señalar que la demostración tiene un alcance limitado y que en una aplicación real, el nivel medio podría
proporcionar adicionalmente servicios como autenticación de los clientes y de las solicitudes que realizan, antes de pasarlos al servicio de
la base de datos.
Las capturas de pantalla a continuación muestran el comportamiento resultante cuando los cinco componentes interactúan correctamente, para la parte B3

de la actividad.
320 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A1 EXPLORANDO ARQUITECTURAS DE DOS Y TRES NIVELES — Cont.


5.8 ARQUITECTURAS DE TRES NIVELES Y MÚLTIPLES 321

ACTIVIDAD A1 EXPLORANDO ARQUITECTURAS DE DOS Y TRES NIVELES — Cont.


Método Parte C: Lograr la transparencia de distribución
La tercera parte de esta actividad se ocupa de lograr los objetivos de transparencia de los sistemas distribuidos; en este caso particular,
nos enfocamos en ocultar los detalles de los servicios de la base de datos y la conectividad de manera que el cliente tenga la ilusión de
que hay una única base de datos conectada localmente. Esto se logra refinando el nivel medio de modo que el cliente solo tenga que
conectarse a un único servidor de aplicaciones que se encarga de la conexión a las bases de datos independientes.
La tercera configuración utiliza una modificación de la implementación de tres niveles utilizada en la parte B. Esta comprende los
siguientes cuatro componentes de software:
DB_Arch_DBServer_DB1_Direct (la implementación del primero de los dos servidores de bases de datos), DB_Arch_DBServer_
DB2_Direct (la implementación del segundo de los dos servidores de bases de datos), DB_Arch_AppServer_for_DB1andDB2
(el nivel medio que se conecta a ambas bases de datos, de forma transparente desde el punto de vista del cliente) y DB_Arch_
AppClient_for_SingleAppServer_DB1andDB2 (un componente de cliente modificado que se conecta al nuevo servidor de aplicaciones de
nivel medio único). Esta configuración corresponde a la parte (c) de Figura 5.21 .
La diferencia importante con la configuración en la parte B es que ahora, el cliente solo conoce su servidor de aplicaciones.
No tiene conocimiento de la forma en que se organizan los datos y no puede decir que los datos se recuperan de dos bases de
datos diferentes. El cliente está acoplado indirectamente a los servidores de la base de datos.
La conectividad y el comportamiento se exploran en tres subpasos.
Parte C1. Ejecute el cliente, el servidor de aplicaciones y el servidor de base de datos DB1. Solicite datos para uno de los ID de cliente y
observe el resultado. Observe que el cliente envía una única solicitud al servidor de aplicaciones (el cliente es
desconoce la configuración de la base de datos). Esta vez, es el servidor de aplicaciones el que gestiona las conexiones a los dos servidores
de bases de datos y, para mayor solidez, las gestiona de forma independiente. Por lo tanto, el servidor de aplicaciones puede devolver
datos parciales al cliente cuando solo una de las bases de datos está conectada.
Parte C2. Repita la parte C1, esta vez solo con el otro servidor de base de datos disponible.
Parte C3. Ejecute el sistema con todos los componentes conectados correctamente. Solicite datos para uno de los ID de cliente y observe el
resultado. El servidor de aplicaciones utiliza la solicitud única enviada por el cliente para crear un par de solicitudes personalizadas, una para cada
base de datos específica. Las respuestas devueltas por las dos bases de datos son enviadas por el servidor de aplicaciones como dos respuestas
separadas al cliente.

Resultado esperado para la Parte C


A través de los experimentos en esta parte de la actividad, debe poder comprender la forma en que se agregó la
transparencia de distribución, donde estuvo ausente en la parte B. El cliente desconoce la presencia de los dos
diferentes bases de datos y sus interfaces. Al cliente se le presenta una vista de sistema único en el sentido de que se conecta al
componente de servidor de aplicaciones único que le proporciona todos los recursos que necesita; el diseño del cliente no está
relacionado con la configuración del resto del sistema.
Al igual que con las otras partes de la actividad, utilice los registros de eventos de diagnóstico proporcionados en el servidor de aplicaciones y los

componentes del servidor de base de datos para inspeccionar el comportamiento en detalle.

Las capturas de pantalla a continuación muestran el comportamiento resultante cuando los cuatro componentes interactúan correctamente, para la parte C3 de

la actividad.
322 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A1 EXPLORANDO ARQUITECTURAS DE DOS Y TRES NIVELES — Cont.

Reflexión
Esta actividad proporciona información sobre el diseño y el funcionamiento de aplicaciones de dos y tres niveles.
La configuración de dos niveles utilizada en la parte A carece de transparencia porque el cliente se conecta directamente con los dos
servidores de base de datos. La segunda configuración introduce el tercer nivel, pero de tal manera que se limita el grado de
transparencia logrado (se proporciona transparencia de acceso y ubicación). La tercera configuración reorganiza el nivel medio para
agregar transparencia a la distribución, de modo que el proceso del cliente esté protegido de los detalles de la organización de la base de
datos y ni siquiera se dé cuenta de que hay varias bases de datos presentes.
Un buen ejercicio para reforzar su comprensión de los conceptos que se muestran en esta actividad es elegir cualquier aplicación distribuida
(algunos ejemplos son la banca, las compras en línea y el comercio electrónico) y esbozar los diseños del esquema para ella, utilizando tanto el de dos
niveles como el de arquitecturas de tres niveles. Evalúe los diseños en términos de su transparencia, escalabilidad y flexibilidad esperadas.

ejemplo de la importancia de la transparencia. Se ha tenido cuidado para garantizar que las aplicaciones
desarrolladas para admitir Actividad A1 Capture tanto el desafío de acceder a múltiples recursos distribuidos
como la transparencia resultante que se puede lograr mediante un diseño adecuado. Tenga en cuenta que la
funcionalidad real de la base de datos que se ha implementado en las aplicaciones exploradas en Actividad
A1 es mínimo; basta con que los ejemplos sean comprensibles, ya que los resultados del aprendizaje de la
actividad se centran en los aspectos comunicacionales y arquitectónicos más que en la base de datos en sí.
5.9 DE IGUAL A IGUAL 323

5.9 DE IGUAL A IGUAL


El término par significa "con la misma categoría"; a menudo se utiliza para describir el estado relativo de las personas, por lo que, por
ejemplo, si eres un estudiante de una clase en particular, tus compañeros de clase son tus compañeros. En software, los pares son
componentes que son iguales en términos de funcionalidad. La descripción peer-to-peer sugiere que para que una aplicación de este
tipo alcance la funcionalidad completa, es necesario que haya varios componentes del mismo nivel interactuando, aunque esto
depende del diseño de la aplicación real y de los componentes del mismo nivel. Para poner esto en contexto, si el propósito de la
aplicación es facilitar el intercambio de archivos, entonces cada componente de pares puede tener algunos archivos almacenados
localmente que puede compartir con otros pares cuando está conectado. Si un usuario ejecuta una instancia de la aplicación en
ausencia de otros pares, solo estarán disponibles los archivos almacenados localmente; esto aún puede ser útil para el usuario. En
contraste con esto, considere un servicio de información de viajes de igual a igual en el que los usuarios comparten información de
viajes local, como noticias de retrasos de trenes o atascos de tráfico, con otros usuarios de la aplicación. El usuario local ya conoce la
información almacenada localmente (porque ellos la crean), por lo que esta aplicación en particular solo es útil cuando se conectan
varios componentes del mismo nivel.

5.9.1 CARACTERÍSTICAS DE LAS APLICACIONES PEER-TO-PEER


La esencia de una aplicación peer-to-peer es que dos o más pares se conectan entre sí para brindar un servicio a los usuarios. Algunas
aplicaciones peer-to-peer están diseñadas para funcionar bien con solo una pequeña cantidad de usuarios (como compartir medios),
mientras que para algunas aplicaciones, la utilidad aumenta en línea con la cantidad de pares conectados; por ejemplo, algunos
juegos se vuelven cada vez más interesantes cuando el número de jugadores alcanza una masa crítica.
Mecánicamente, si los pares son simétricos, cualquier instancia puede ofrecer servicios a los demás. Esto significa que
en una aplicación típica de igual a igual, cualquier componente puede ser un proveedor de servicios o un solicitante de
servicios, en diferentes momentos según las circunstancias. Esta es una diferencia significativa con los modelos CS y de tres
niveles, en los que los diversos componentes tienen roles predeterminados que no son reversibles, por ejemplo, un cliente y
un servidor no pueden intercambiar roles porque los comportamientos específicos están integrados en la lógica diferente
de cada componente. tipo.
Desde el punto de vista de la interacción, las aplicaciones peer-to-peer tienden a
depender del descubrimiento automático y la conexión entre pares. Las interacciones a
veces son "casuales" debido a la coexistencia de usuarios con necesidades relacionadas.
Por ejemplo, peer-to-peer es popular entre los dispositivos móviles para jugar y compartir
archivos / medios, utilizando enlaces inalámbricos como Bluetooth para la conexión. Si
dichas aplicaciones están habilitadas en los dispositivos, se establecerá automáticamente
una conexión cuando los dispositivos estén muy cerca unos de otros. Dado que
generalmente no es predecible cuándo los compañeros entrarán en contacto y
establecerán relaciones, las aplicaciones de igual a igual a menudo se describen como que
tienen un comportamiento de interacción ad hoc. Esto contrasta con el modelo CS,
Las características generales de las aplicaciones peer-to-peer se pueden resumir de la siguiente manera:

• Los compañeros se comunican con otros para lograr su función (por ejemplo, juegos, mensajería y uso compartido de
• archivos). Las aplicaciones suelen tener un alcance limitado (normalmente con una única función principal) y el requisito
de conexión a "otros" remotos de forma sencilla y flexible.
• La conectividad es ad hoc (es decir, puede ser espontánea, no planificada y no estructurada). Los compañeros pueden
• interactuar con otros en cualquier orden y en cualquier momento. Figura 5.23 captura la esencia de esto. Peer-to-peer se
• adapta bien a aplicaciones móviles en dispositivos móviles.
324 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Comunicación Proceso Comunicación


en el momento t 0 B en el momento t 1

Proceso Proceso
A C
Comunicación
en el momento t 2

FIGURA 5.23

Los pares se comunican con diferentes vecinos en diferentes momentos según los requisitos de la aplicación y la disponibilidad de los
pares.

Figura 5.23 ilustra la naturaleza dinámica de las aplicaciones peer-to-peer, en las que los pares pueden unirse o salir de forma
independiente en varios momentos. Por lo tanto, es posible que un grupo de pares no estén todos presentes o no se conecten entre
sí al mismo tiempo; las conexiones pueden ocurrir de manera oportunista a medida que se encuentran disponibles diferentes pares.

5.9.2 COMPLEJIDAD DE LA CONECTIVIDAD PEER-TO-PEER


La complejidad de la conectividad de igual a igual es potencialmente mucho mayor que en otras arquitecturas, que
están más estructuradas. En CS, la cantidad de conexiones a un servidor dado es una por cliente, por lo que si hay norte
clientes, hay norte conexiones al servidor; por lo tanto, decimos que la complejidad de la interacción es "orden norte ”Declaró
O ( norte). Esta es una relación lineal. Con esto en mente, considere un escenario de igual a igual en el que hay cinco
pares presentes y hay múltiples conexiones establecidas de manera ad hoc entre ellos. 2 Un posible resultado se
muestra en Figura 5.24 .
Figura 5.24 muestra una configuración de cinco pares con un total de siete conexiones entre los pares. El
número máximo de conexiones que ocurrirían si todos los pares conectados entre sí fueran diez, en cuyo
caso cada par tendría cuatro conexiones con otros pares. Existe un cálculo que puede usarse para
determinar el número máximo de conexiones que pueden ocurrir entre un cierto número de pares, dado en
la fórmula (5,1) :
PÁGINAS 1)
C=(- (5,1)
2

dónde PAG es el número de compañeros presentes y C es el número máximo de conexiones resultante. Insertemos algunos
valores: para cuatro pares, obtenemos C = ( 4 * 3) / 2 = 6; para cinco pares, obtenemos C = ( 5 * 4) / 2 = 10; mientras que para
seis pares, obtenemos C = ( 6 * 5) / 2 = 15, y si consideramos diez pares, obtenemos C = ( 10 * 9) / 2 = 45. Esto claramente está
aumentando de una manera más empinada que lineal. Este patrón de aumento se describe generalmente

2 La frase "conexiones establecidas de manera ad hoc" significa esencialmente que habrá varias conexiones establecidas entre un par
en particular y sus vecinos, dependiendo quizás de la secuencia con la que pares específicos se unieron al grupo (porque algunas
aplicaciones pueden limitar el número de pares al que se conecta un individuo), y el rango real entre cada par de individuos (por lo
que los diferentes subconjuntos son visibles para cada individuo). Por lo tanto, el mapeo exacto de conexiones puede no ser
predecible y puede ser diferente incluso en situaciones similares (ligeramente diferentes).
5.9 DE IGUAL A IGUAL 325

Proceso
B Proceso
D

Proceso
A

Proceso
mi
Proceso
C

FIGURA 5.24

Conectividad ad hoc en arquitecturas peer-to-peer.

como exponencial, y en este caso particular, tiene orden O (( n (n - 1)) / 2), que se deriva de la fórmula (5,1) . Con un
patrón de intensidad de comunicación en aumento tan pronunciado, en algún momento, el número de conexiones
y los gastos generales de comunicación asociados afectarán el rendimiento de la aplicación, lo que limitará la
escalabilidad. En otras palabras, existe un límite en la escala a la que el sistema puede crecer y seguir funcionando
correctamente y con capacidad de respuesta.
Sin embargo, algunos sistemas peer-to-peer están diseñados de manera que los pares se conectan solo a un subconjunto de
vecinos (es decir, aquellos otros pares que están en el rango de comunicación). Por ejemplo, algunas aplicaciones (incluidas algunas
aplicaciones de redes de sensores) dependen de la conectividad entre pares para formar una cadena para pasar información a través
de un sistema.

5.9.3 EXPLORANDO EL COMPORTAMIENTO ENTRE PARES

Como se mencionó anteriormente, una aplicación popular para arquitecturas peer-to-peer es el intercambio de medios
(como fotos y canciones) y es especialmente popular en plataformas móviles como teléfonos y tabletas.
Se ha desarrollado una aplicación peer-to-peer para compartir medios, MediaShare_Peer, para facilitar la
exploración práctica de una aplicación peer-to-peer y se utiliza en Actividad A2 . La exploración incluye aspectos de la
forma en que funcionan los sistemas peer-to-peer, sus beneficios en términos de flexibilidad y conectividad ad hoc,
y la forma en que se puede lograr la configuración automática.

ACTIVIDAD A2 EXPLORACIÓN DE LA ARQUITECTURA PEER-TO-PEER


Se utiliza una aplicación para compartir medios para explorar varios aspectos importantes de la arquitectura de igual a igual.
La aplicación se basa en el concepto de que cada usuario tiene algunos archivos de música que está preparado para compartir
con otros usuarios, de forma homogénea. El usuario ejecuta una única instancia de igual. Cuando no hay otros pares disponibles, el
usuario puede reproducir solo las canciones contenidas en la instancia local. Cuando se detecta otro par, los dos pares se descubren
automáticamente (en términos de sus direcciones) y, por lo tanto, forman una asociación (el término conexión es
326 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A2 EXPLORACIÓN DE LA ARQUITECTURA PERMANENTE — Cont.


evitado porque podría implicar el uso de un protocolo de transporte orientado a la conexión, como TCP, cuando en realidad esta aplicación usa UDP,
en parte debido a la capacidad de UDP para transmitir, que es necesaria para el descubrimiento automático de pares). Luego, los pares intercambian
detalles de los archivos multimedia que cada uno tiene. En este punto, la pantalla del usuario se actualiza para reflejar el conjunto más amplio de
recursos disponibles para el usuario (el usuario ahora puede reproducir cualquiera de los archivos de música almacenados en cualquiera de los
pares).
La aplicación de demostración muestra diversa información de diagnóstico, incluido un registro de eventos, que indica lo que está
sucediendo detrás de escena, como el descubrimiento de otros pares, y también indica qué compañero específico ha proporcionado
cada archivo de música. Esta información se incluye específicamente para mejorar los resultados de aprendizaje de la actividad; en una
aplicación real, no es necesario que el usuario vea dicha información.
Para evitar una complejidad innecesaria en la aplicación de demostración, solo se transfieren los nombres de los archivos de recursos (es
decir, una lista de nombres de archivos de música) y no los archivos de música en sí. En una implementación real, cuando un usuario desea
reproducir una canción, el archivo de datos de la canción real necesitaría ser transferido si no está ya guardado localmente. Esta simplificación no
afecta el valor de la actividad ya que está enfocada a demostrar los aspectos de transparencia y descubrimiento de pares.

Prerrequisitos
Copie los materiales de apoyo requeridos por esta actividad en su computadora; consulte la Actividad I1 en el Capítulo 1.

Los resultados del aprendizaje


Para comprender la arquitectura de igual a igual
Familiarizarse con un ejemplo específico de aplicación peer-to-peer Apreciar
la necesidad de un descubrimiento de pares dinámico y automático
Comprender una técnica para lograr el descubrimiento automático de pares.
Apreciar la necesidad de transparencia en las aplicaciones distribuidas.
Explorar la disposición de transparencia en la aplicación de demostración La
actividad se realiza en tres etapas principales.

Método Parte A: Ejecutar un par en aislamiento


Esta parte de la actividad implica ejecutar una sola instancia del programa MediaShare_Peer en una sola computadora. Anote el número de
identificación del compañero, la lista de canciones y artistas que se muestran y las entradas del registro de eventos de diagnóstico. Cierre la instancia
del mismo nivel e iníciela de nuevo, varias veces, cada vez teniendo en cuenta los datos que se muestran. Verá que la aplicación de demostración ha
sido diseñada para generar un ID único de forma aleatoria y también para seleccionar sus archivos de música locales de forma aleatoria, de modo
que el programa único se puede utilizar para simular numerosos pares con diferentes configuraciones, sin que el usuario tenga que configurarlo
manualmente. .

Resultado esperado para la Parte A


Este paso brinda la oportunidad de familiarizarse con la aplicación en el escenario más simple. También demuestra dos conceptos importantes: en
primer lugar, un solo par funciona correctamente de forma aislada (es decir, no falla ni se comporta de manera extraña cuando no hay otros pares
disponibles, sino que funciona correctamente como una aplicación de igual a igual que simplemente tiene solo un par). En segundo lugar, un usuario ve
una lista de recursos (archivos de canciones en este caso) disponibles para su uso. Dependiendo de los requisitos reales de la aplicación, generalmente
se deseará que los recursos almacenados localmente estén siempre disponibles para el usuario local independientemente de la configuración más
amplia de los otros pares.
La siguiente captura de pantalla muestra un único par que opera de forma aislada. Los archivos multimedia que se enumeran como disponibles son los

recursos almacenados localmente y, por lo tanto, un usuario puede acceder a ellos (es decir, reproducir las bandas sonoras) sin necesidad de componentes

adicionales.
5.9 DE IGUAL A IGUAL 327

ACTIVIDAD A2 EXPLORACIÓN DE LA ARQUITECTURA PERMANENTE — Cont.

Método Parte B: Descubrimiento automático de pares


Dejando en ejecución la instancia del par local (de la parte A), inicie otra instancia en otra computadora en la misma red local (esto es
importante porque se usa la comunicación de transmisión, que está bloqueada por los enrutadores). También puede confirmar
empíricamente que solo se puede operar una instancia de pares en cada computadora (intente ejecutar dos copias en una computadora).
Esta restricción surge porque cada par tiene que vincularse a los dos puertos de aplicación que se utilizan (uno para recibir mensajes de
autoadvertencia de pares para el descubrimiento automático de pares y otro para recibir los mensajes de la aplicación de par a par).
El descubrimiento se logra cuando cada par envía un mensaje de auto-publicidad (tipo de mensaje
PEER_SELF_ADVERTISEMENT) que contiene el ID único del par emisor, así como la dirección IP y los detalles del número de
puerto que deben usarse cuando los mensajes de la aplicación se envían a ese par. Al recibir estos mensajes, un par almacena
los detalles en su propia matriz de conocidos_peers local. Esto permite al destinatario de futuros mensajes de auto-publicidad
distinguir entre pares que ya conoce y nuevos pares.
El descubrimiento de un nuevo par activa automáticamente el envío de un mensaje de solicitud a ese par (tipo de mensaje
REQUEST_MEDIA_LIST), lo que hace que el par responda con una serie de mensajes de datos (tipo de mensaje SEND_MEDIA_RECORD), cada uno de
los cuales contiene detalles de un elemento de datos de medios. Tenga en cuenta que en la aplicación de demostración, solo se transfieren el título
de la canción y el nombre del artista, pero en una aplicación real para compartir medios, el archivo de música real podría transferirse a pedido.

Resultado esperado para la Parte B


Debería ver la actividad de detección automática de pares en curso, seguida de la transferencia de información de recursos de medios
disponibles entre los pares. La información de diagnóstico no se mostraría en una aplicación real, ya que los usuarios no necesitan saber
qué pares proporcionan qué recursos, ni siquiera estar al tanto de la existencia de los pares remotos, o ver cualquier otra información
relativa a la estructura o conectividad de la aplicación. sí mismo. Cada usuario solo vería los recursos multimedia disponibles para ellos y
podría acceder a ellos de la misma manera independientemente de la ubicación, es decir, la aplicación proporciona transparencia de
acceso y ubicación.
Las capturas de pantalla a continuación muestran las dos instancias de pares en dos computadoras separadas después de que cada una haya
descubierto al otro par. La primera imagen es del mismo par que se muestra en la parte A anterior (se dejó ejecutándose) y la segunda imagen es del
segundo par que se inició en una computadora diferente durante la parte B de esta actividad.
328 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A2 EXPLORACIÓN DE LA ARQUITECTURA PERMANENTE — Cont.

Método Parte C: Comprensión del protocolo de nivel de aplicación


Este paso implica una mayor investigación para reforzar la comprensión. En particular, la atención se centra en el protocolo a nivel de
aplicación, es decir, la secuencia de mensajes que se pasan entre los componentes, los tipos de mensajes y el contenido del mensaje.

Parte C1. Ejecute la aplicación varias veces con dos pares cada vez. Observe de cerca las entradas que se muestran en el registro de
actividades. A partir de esto, intente trazar el protocolo de nivel de aplicación (es decir, la secuencia de mensajes) que se utiliza en el
descubrimiento mutuo y el intercambio mutuo posterior de datos de medios entre los pares.
5.10 OBJETOS DISTRIBUIDOS 329

ACTIVIDAD A2 EXPLORACIÓN DE LA ARQUITECTURA PERMANENTE — Cont.


Sugerencias: cada par tiene la misma lógica de programa. El descubrimiento de pares y el intercambio de medios operan de forma independiente

en cada dirección, debido al diseño simétrico intencionado que fue posible en este caso y que hace que la aplicación sea más
simple de diseñar, desarrollar y probar. Por lo tanto, solo es necesario mapear los mensajes necesarios para un par (par
A) para descubrir otro par (par B), para solicitar al par B que envíe sus datos de medios y para que el par B responda a esa solicitud
enviando realmente sus datos. La misma secuencia ocurre cuando el par B descubre al par A.
Parte C2. Ejecute la aplicación con al menos tres compañeros. Verifique que su mapeo del protocolo de nivel de aplicación aún sea
correcto en estos escenarios más complejos.
Además de la evaluación empírica mediante la ejecución de la aplicación, también puede examinar el código fuente de la
aplicación, que se proporciona, para confirmar sus hallazgos y también para inspeccionar el contenido real de los distintos tipos de
mensajes.
Se proporciona un diagrama que muestra la secuencia de mensajes del protocolo a nivel de aplicación en un Apéndice al final del
capítulo para que pueda verificar sus hallazgos.

Reflexión
Esta actividad ha apoyado la exploración empírica de dos aspectos importantes de las aplicaciones peer-to-peer: en primer lugar, una
demostración del descubrimiento automático entre componentes, en la que cada par mantiene la información adecuada en una tabla
para poder diferenciar a los pares recién descubiertos de los pares previamente conocidos. y, en segundo lugar, una investigación de
los requisitos de transparencia y la provisión de transparencia en aplicaciones distribuidas. Los aspectos de transparencia que son más
pertinentes en esta aplicación en particular son que el usuario no necesita saber qué otros pares están presentes, dónde se
encuentran o el mapeo de qué archivos de música se mantienen en cada par. En una aplicación completamente transparente, el
usuario verá solo una lista de recursos disponibles; si la información de diagnóstico se eliminó de la interfaz de usuario de la aplicación
de demostración,
Estos aspectos de mecanismo y comportamiento son de fundamental importancia para el diseño de una amplia variedad de aplicaciones
distribuidas. Repita los experimentos y observe el comportamiento unas cuantas veces más si es necesario hasta que comprenda claramente
lo que está sucediendo y cómo se logra el comportamiento.

5.10 OBJETOS DISTRIBUIDOS


La característica distintiva del enfoque de objetos distribuidos es que divide la funcionalidad de una
aplicación en muchos componentes pequeños (basados en los objetos en el código), lo que permite que se
distribuyan de formas muy flexibles entre las computadoras disponibles.
Desde la perspectiva del número de componentes creados, el enfoque de objetos distribuidos puede mostrar cierta
semejanza con las arquitecturas de varios niveles discutidas anteriormente. Sin embargo, existen diferencias importantes en
cuanto a la granularidad y la base funcional sobre la que se realiza la separación. El código orientado a objetos separa la
lógica del programa en secciones relacionadas funcionalmente y / o específicas relacionadas con datos (los objetos). En la
mayoría de las aplicaciones, los componentes se implementan en un grano más grueso que el nivel de objeto. Por ejemplo,
un cliente (en una aplicación CS o de varios niveles) puede comprender un código de programa que se divide internamente
en varios objetos a nivel de código, pero estos objetos se ejecutan juntos como un único proceso coherente en el nivel de
componente del cliente y de manera similar para el servidor. componente (s). A diferencia de, Los objetos distribuidos tienen
como objetivo una división detallada de la funcionalidad al crear los componentes de software, basándose en la partición de
los objetos reales a nivel de código en componentes separados. Por lo tanto, cuando se comparan los objetos distribuidos y
los enfoques de varios niveles, generalmente deberíamos esperar ver que la implementación de los objetos distribuidos
comprenda un mayor número de objetos más pequeños (o más simples), quizás cada uno de ellos realizando una única
función específica.
330 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

El énfasis en la ubicación de los componentes de los dos enfoques también es diferente. Las arquitecturas de varios
niveles se preocupan principalmente por la estructura del software y la división de la lógica empresarial entre los diversos
componentes, que es fundamentalmente una preocupación en el tiempo de diseño. El enfoque de objetos distribuidos
soporta mejor las decisiones en tiempo de ejecución para la ubicación de instancias de componentes, ya que opera en el
nivel de objetos individuales y puede tener en cuenta sus requisitos de recursos específicos en tiempo de ejecución.
Sin embargo, un desafío principal de una división tan fina de la funcionalidad es el número de conexiones entre los
componentes y la cantidad de comunicación que se produce. Puede haber oportunidades para mejorar el rendimiento
asegurándose de que los pares de componentes que interactúan intensamente se mantengan ubicados en la misma
computadora física.
Figura 5.25 proporciona una distribución ilustrativa de siete objetos en cinco computadoras, como
parte de una aplicación de banca distribuida. La ubicación del objeto puede ser dinámica en función
de la disponibilidad de recursos y las relaciones de comunicación entre los componentes pueden
cambiar con el tiempo; por lo tanto, el título describe la configuración como una instantánea (puede
ser diferente en otros momentos). Tenga en cuenta que puede haber varios objetos del mismo tipo
(como "Cuenta de cliente" en el ejemplo), así como objetos de diferentes tipos repartidos por el
sistema. La figura también muestra cómo los servicios de un objeto en particular (como
"Autenticación" en el ejemplo) pueden ser utilizados por varios otros objetos bajo demanda. Los
objetos se comunican haciendo llamadas a métodos entre sí, por ejemplo, para ejecutar una
transacción en moneda extranjera,
Figura 5.25 también ilustra algunos de los beneficios diferenciales de la arquitectura de objetos distribuidos en
comparación con los de varios niveles. En el ejemplo que se muestra, la funcionalidad de una aplicación se ha
dividido en muchos componentes de software. El beneficio de esto es la flexibilidad con la que los componentes se
pueden distribuir, por ejemplo, para ubicarse en función de la proximidad a recursos específicos. La ubicación de

Clave:

Objeto que se ejecuta como


un proceso independiente
Tasa de interés
calculadora Límite físico de la computadora

Los tipos de cambio

convertidor

Hipoteca Extranjero

pago divisa
gerente transacción
Autenticación
gerente

Cliente
Cliente
cuenta # 1435
cuenta # 4810

FIGURA 5.25

Una aplicación de objetos distribuidos; una instantánea en tiempo de ejecución.


5.11 MIDDLEWARE: SOPORTE PARA ARQUITECTURAS DE SOFTWARE 331

Los objetos también se pueden realizar sobre una base de equilibrio de carga. Por ejemplo, si hay varios objetos (del mismo
tipo) en el sistema que requieren una gran cantidad de recursos de procesamiento, el enfoque de objetos distribuidos
permite que estos objetos se ejecuten en diferentes sitios físicos (procesadores). Mientras que, con la arquitectura de varios
niveles, si todos estos objetos requieren el mismo tipo de procesamiento, todos tendrían que hacer cola para ser
procesados por un componente de servidor en particular que proporcione la función requerida.
Se necesita cierta infraestructura para admitir un entorno de objetos distribuidos. Los requisitos de soporte específicos
incluyen un medio para que los objetos se identifiquen de forma única en el sistema, un medio para que los objetos se
ubiquen entre sí y un medio para que los objetos se comuniquen (realizar llamadas a métodos remotos entre sí). El
middleware se usa comúnmente para proporcionar este soporte; vea la siguiente sección.

5.11 MIDDLEWARE: SOPORTE PARA ARQUITECTURAS DE SOFTWARE


Esta sección trata sobre la forma en que el middleware admite arquitecturas de software. En el Capítulo 6 se
proporciona una discusión más detallada del funcionamiento del middleware y las formas en que proporciona
transparencia a las aplicaciones.
El middleware es esencialmente una capa de software que se encuentra conceptualmente entre los procesos y
la red de computadoras. Proporciona a las aplicaciones la abstracción de una única plataforma de procesamiento
coherente, ocultando detalles del sistema físico real, incluido el número de procesadores y la distribución y
ubicación de recursos específicos.
Middleware proporciona una serie de servicios a las aplicaciones para admitir arquitecturas de software basadas en
componentes en las que muchos componentes de software se distribuyen dentro del sistema y necesitan ayuda, por
ejemplo, para ubicarse entre sí y pasar mensajes. El middleware es muy importante para los sistemas de software
dinámicos, como los objetos distribuidos, porque la ubicación de los componentes de software reales puede no ser fija o al
menos no decidida en el tiempo de diseño.

5.11.1 FUNCIONAMIENTO DE MIDDLEWARE, DESCRIPCIÓN GENERAL

La siguiente discusión sobre cómo funciona el middleware se centra en los principios generales de funcionamiento porque
en realidad hay muchas tecnologías de middleware específicas con varias diferencias y características especiales para tipos
particulares de sistemas (los ejemplos incluyen soporte para aplicaciones de computación móvil y soporte para
procesamiento en tiempo real).
Middleware proporciona un identificador único para cada objeto de aplicación que se admite en el sistema. Cuando se
crean instancias de estos objetos como procesos en ejecución, el middleware realiza un seguimiento de su ubicación física
(es decir, en qué procesador real se están ejecutando) en una base de datos que, a su vez, puede distribuirse entre las
diversas computadoras del sistema (al igual que los procesos que constituyen el middleware en sí). El middleware también
puede realizar un seguimiento de la ubicación física de ciertos tipos de recursos que utiliza la aplicación.

Con base en su información almacenada de qué objetos (que se ejecutan como procesos) y recursos están
presentes y dónde se encuentran, el middleware proporciona servicios de conectividad transparentes, esenciales
para el funcionamiento de las aplicaciones en el sistema. Un proceso puede enviar un mensaje a otro proceso
basándose únicamente en el ID único del proceso de destino. El middleware usa el ID del proceso para localizar el
proceso y entregarle el mensaje, y luego pasa cualquier mensaje de respuesta al proceso remitente. Esto se logra
sin que ninguno de los procesos tenga que conocer la ubicación física real del
332 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

otro proceso, y opera de la misma manera si los procesos son locales entre sí (en el mismo
procesador) o remotos. Esta ubicación transparente y dinámica de objetos (procesos) también permite
el movimiento de objetos dentro del sistema o que los objetos se cierren en una ubicación y
posteriormente se ejecuten en otra ubicación; el middleware siempre sabrá el ID del objeto y su
ubicación actual.
Es importante reconocer que el middleware juega el papel de facilitador de la comunicación. El
middleware no forma parte de ninguna de las aplicaciones que admite, sino un servicio externo. Como tal, el
middleware no participa en la conectividad de nivel empresarial dentro de la aplicación; no comprende el
significado o el contenido de los mensajes ni tampoco las funciones específicas de los distintos objetos de
aplicación presentes.
Al utilizar el middleware para facilitar la conectividad, los objetos no necesitan tener información incorporada
sobre la dirección o ubicación de los otros componentes con los que se comunican, y las aplicaciones no necesitan
admitir sus propios mecanismos de descubrimiento de componentes (un ejemplo de tales se encuentra en el
ejemplo MediaShare_Peer discutido anteriormente). Por lo tanto, al utilizar los servicios de middleware, las
aplicaciones pueden aprovechar la conectividad dinámica y automatizada en tiempo de ejecución. Esta es una forma
de acoplamiento flexible en el que el middleware es el servicio intermediario. Esto tiene los beneficios de la
flexibilidad (porque los componentes se pueden colocar en los procesadores en función de la disponibilidad de
recursos dinámicos) y la solidez (porque la aplicación no depende de una asignación rígida de componentes a
ubicaciones físicas). Otro beneficio importante es que el diseño del software de la aplicación se simplifica al no tener
que administrar la conectividad directamente; el valor de este beneficio aumenta drásticamente para aplicaciones
más grandes con muchos objetos que interactúan.
Figura 5.26 describe cómo la presencia del middleware como una capa virtual oculta los detalles de la ubicación real de
los procesos y los hace igualmente accesibles independientemente de la ubicación real. Esto significa que un proceso no
necesita saber dónde se encuentran físicamente en el sistema otros procesos con los que se comunica. Un proceso está
desacoplado de la plataforma subyacente incluso si está alojado físicamente en ella. Desde un punto de vista lógico, todos
los procesos son igualmente visibles desde cualquier plataforma y todos los recursos de la plataforma son igualmente
accesibles para todos los procesos.

Proceso Proceso Proceso


A B C

Middleware

Sistema operativo Sistema operativo Sistema operativo

Plataforma / hardware Plataforma / hardware Plataforma / hardware

FIGURA 5.26

Descripción general de middleware.


5.12 MODELOS DE SISTEMAS DE RECURSOS COLECTIVOS 333

5.12 MODELOS DE SISTEMA DE RECURSOS COLECTIVOS Y SUMINISTRO DE RECURSOS


DE COMPUTACIÓN
Hay tendencias en constante evolución en las formas en que se proporcionan los recursos informáticos. Esta sección trata
de los diversos modelos de provisión informática que son importantes para los desarrolladores de aplicaciones distribuidas.

Para implementar aplicaciones distribuidas exitosas, además del diseño de las arquitecturas de software
de las aplicaciones en sí mismas (que es la principal preocupación de este libro), también es necesario
considerar cuidadosamente el diseño de los sistemas de computadoras en las que se ejecutan estas
aplicaciones. . Es probable que el desarrollador de software no participe directamente en la selección del
hardware de procesamiento y las tecnologías de red que los unen. Sin embargo, es importante que los
desarrolladores de software comprendan la naturaleza de los diversos modelos de sistemas comunes y los
impactos que estos pueden tener en el nivel de recursos disponibles para las aplicaciones, así como
problemas como la robustez y la latencia de la comunicación que pueden tener impactos en el
comportamiento general en tiempo de ejecución.
Para comprender completamente los diversos modelos de provisión de recursos informáticos en el contexto moderno,
es útil considerar brevemente algunos aspectos de la historia de los sistemas informáticos.
A partir de la llegada de la PC a principios de la década de 1980, el costo de la potencia
informática estuvo repentinamente al alcance de la mayoría de las empresas donde
anteriormente había sido prohibitivamente caro. Inicialmente, la mayoría de las
aplicaciones eran independientes y se utilizaban para la automatización de tareas
mundanas pero importantes, como la gestión de cuentas y niveles de existencias, así como
actividades de oficina electrónica como el procesamiento de textos. Las redes de área local
se convirtieron en algo común dentro de las organizaciones unos años más tarde (hacia
fines de la década de 1980), y esto revolucionó los tipos de aplicaciones que se utilizaban.
Ahora, era posible acceder a recursos como bases de datos y dispositivos físicos como
impresoras que estaban ubicadas en otras computadoras dentro del sistema.

El siguiente paso fue la amplia disponibilidad de conexiones a Internet. Esto permitió la transferencia de datos de alta
velocidad entre sitios dentro de las organizaciones y entre las propias organizaciones. Aplicaciones como el correo
electrónico y el comercio electrónico y el acceso en línea a datos y servicios revolucionaron el papel de la computadora en el
lugar de trabajo (y en otros lugares).
Durante esta secuencia de eventos, la cantidad real de computadoras propiedad de las organizaciones creció
dramáticamente, hasta el punto en el que hoy nos encontramos con casi todos los empleados en una amplia gama de roles
de trabajo que tienen una computadora dedicada y dependen del uso de esa computadora para llevar a cabo una
proporción significativa de sus tareas laborales.
Además de las computadoras de acceso o front-end, también hay que considerar las computadoras de provisión de
servicios. En los días de la informática autónoma, los recursos estaban todos en una sola máquina. En los días del acceso
remoto a los recursos, a través de redes locales, las computadoras que alojaban los recursos eran esencialmente las mismas
en términos de configuración de hardware y niveles de recursos que las computadoras de acceso. De hecho, un usuario de
oficina podría tener acceso remoto a una impresora conectada a la computadora de un colega con exactamente la misma
especificación de hardware que la suya. Sin embargo, una vez que la informática distribuida se hizo popular, las plataformas
que alojaban los servicios debían ser más potentes: necesitaban más espacio de almacenamiento.
334 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

en los discos duros, más memoria, procesadores más rápidos y enlaces de red más rápidos. Las organizaciones se volvieron cada vez
más dependientes de estos sistemas, de modo que no podían tolerar el tiempo de inactividad y, por lo tanto, se emplearon equipos
expertos de ingenieros de sistemas. Los recursos de alojamiento de servicios y su infraestructura de soporte, incluido el personal, se
convirtieron en un importante centro de costos para las grandes organizaciones, que requerían una gestión especializada.

Además, la mayoría de las organizaciones involucradas en negocios, finanzas, venta minorista, fabricación y prestación de
servicios (como hospitales y gobiernos locales), de hecho, casi todas las organizaciones, tienen necesidades complejas de
procesamiento informático, que requieren muchas aplicaciones diferentes que se ejecutan y utilizan una amplia variedad. de
diferentes recursos de datos. Priorizar entre estas actividades informáticas para garantizar el uso eficiente de los recursos puede ser
muy complejo y, por lo tanto, el modelo simple de provisión de recursos de simplemente comprar computadoras con plataformas de
alojamiento de servidores cada vez más caras se vuelve inadecuado y se necesita una base de recursos más estructurada.

Como resultado de estos desafíos, han evolucionado varias categorías de sistemas de provisión de recursos en los que
los recursos se agrupan y administran colectivamente para proporcionar un servicio informático. Los diversos enfoques
enfatizan de manera diferente una serie de objetivos que incluyen el aumento de la potencia informática total disponible
para las aplicaciones (especialmente los sistemas de clúster); agrupación lógica de recursos específicos de aplicaciones
privadas para mejorar la gestión y la eficiencia de la informática (especialmente los sistemas de red); la provisión de
computación como servicio para reducir el costo de propiedad del procesamiento y almacenamiento (especialmente los
centros de datos); y entornos virtuales robustos y a gran escala donde se gestionan la informática y el almacenamiento
(especialmente los sistemas en la nube).

5.12.1 CLUSTERS
La computación en clúster se basa en el uso de un grupo dedicado de unidades de procesamiento, generalmente
propiedad de una sola organización y, a menudo, reservada para ejecutar aplicaciones específicas. Los
procesadores suelen estar conectados de forma flexible (es decir, conectados por una red; consulte Sección 5.4 ) y se
gestionan con un software especial para que se utilicen colectivamente y los clientes del clúster los vean como un
solo sistema.

5.12.2 REJILLAS
La computación en cuadrícula se basa en recursos informáticos distribuidos físicamente que se utilizan de manera
cooperativa para ejecutar una o más aplicaciones. Los recursos pueden ser propiedad de varias organizaciones y el
objetivo principal es el procesamiento eficiente de aplicaciones específicas que necesitan acceso a recursos
específicos, por ejemplo, puede haber recursos de datos en varias ubicaciones a las que una aplicación en particular
debe acceder. Para garantizar el rendimiento y la eficiencia de la ejecución de las aplicaciones, estos recursos se
pueden unir dentro de una estructura con administración común y procesadores dedicados (una cuadrícula).

Por lo general, las cuadrículas se diferencian de la computación en clúster en que las primeras tienden a tener
recursos distribuidos geográficamente, que también suelen ser heterogéneos y no se limitan a los recursos
informáticos físicos, pero pueden incluir recursos específicos de la aplicación, como archivos y bases de datos,
mientras que los recursos del clúster son fundamentalmente los propios procesadores físicos y están más
localizados y probablemente sean homogéneos para proporcionar una plataforma informática de alto rendimiento.
5.13 BIBLIOTECAS DE SOFTWARE 335

5.12.3 CENTROS DE DATOS


Los centros de datos se caracterizan por colecciones muy grandes de recursos de procesamiento y almacenamiento propiedad de una empresa

de prestación de servicios. La capacidad de procesamiento se ofrece como un servicio a las organizaciones que necesitan grandes conjuntos de

recursos informáticos. Los centros de datos típicos tienen miles de unidades de procesamiento, por lo que una organización puede alquilar

tantas como sea necesario para ejecutar aplicaciones paralelas o distribuidas.

El uso de centros de datos reduce el costo de propiedad de los recursos de procesamiento y


almacenamiento porque las organizaciones pueden usar lo que necesitan, cuando lo necesitan, en
lugar de tener que poseer y administrar sus propios sistemas. Una ventaja particular surge cuando
una organización necesita un gran grupo de recursos adicional durante un corto período de tiempo, y
el centro de datos puede alquilárselo inmediatamente sin el retraso ni el costo de tener que configurar
el recurso internamente. Los costos a largo plazo asociados con el arrendamiento de recursos en lugar
de poseerlos pueden compensarse aún más por el hecho de que las organizaciones de usuarios no
necesitan dedicar grandes áreas de espacio con aire acondicionado a los servicios de alojamiento local
y tampoco tienen que preocuparse por expandir sistemas a lo largo del tiempo o actualizando
continuamente las plataformas de hardware y realizando actualizaciones de software operativo.
Además,

5.12.4 NUBES
La computación en la nube se puede considerar como un conjunto de servicios informáticos, incluidos el procesamiento y el
almacenamiento, que un proveedor de servicios proporciona de forma virtualizada. Los recursos de procesamiento reales
generalmente los proporciona un centro de datos subyacente, pero el concepto de nube brinda transparencia de tal manera que la
infraestructura y su configuración son invisibles para los usuarios.
Además del uso de instalaciones en la nube para el procesamiento, actualmente se hace mucho énfasis en el almacenamiento de
datos masivos, y esto es cada vez más popular para su uso con dispositivos móviles y aplicaciones informáticas móviles. Las
colecciones de archivos multimedia, como videos, canciones e imágenes, pueden ser enormes en términos de requisitos de
almacenamiento y superar fácilmente el almacenamiento disponible en los dispositivos locales de los usuarios, como tabletas y
teléfonos inteligentes. Las instalaciones en la nube permiten a los usuarios cargar sus archivos en espacios de almacenamiento muy
grandes (que son relativamente grandes en comparación con las capacidades de sus dispositivos físicos) y también ofrecen la ventaja
de que los usuarios pueden acceder a sus archivos desde cualquier lugar y también compartirlos con otros. usuarios.
El énfasis de la computación en la nube está hacia una extensión de los recursos informáticos personales (pero cambiados a una
forma centralizada y administrada) en la que el almacenamiento en la nube se asigna permanentemente a usuarios específicos. Por el
contrario, el enfoque del centro de datos se centra más en un servicio de computación bajo demanda rentable. En algunos aspectos,
un sistema en la nube se puede considerar como un conjunto de servicios alojados en la infraestructura de un centro de datos.

5.13 BIBLIOTECAS DE SOFTWARE


Los programas simples con funcionalidad limitada se pueden desarrollar como un solo archivo fuente que contiene el
código del programa. Estos programas son cada vez más raros a medida que aumenta el alcance de la funcionalidad y la
complejidad de las aplicaciones. Las complejidades adicionales surgen de aspectos que incluyen soporte de múltiples
plataformas, conectividad con otros componentes y personalización del usuario. También hay una tendencia creciente
336 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

para que los componentes de software tengan una creciente inteligencia incorporada o inteligencia para hacer
frente a situaciones de forma dinámica. Estas aplicaciones pueden ser muy complejas y no es factible escribirlas
como programas únicos. Algún software altamente funcional, como las aplicaciones de oficina electrónica, así como
los propios sistemas operativos, pueden alcanzar cientos de miles de líneas de código; y es muy probable en tales
casos que sean desarrollados por grandes equipos de desarrolladores. Hay muchas aplicaciones para las que es
poco probable que un solo desarrollador comprenda completamente cada línea de código y su propósito dentro de
la propia aplicación.
Una biblioteca es una colección de funciones de programa que están relacionadas de alguna manera. Esto podría ser un
tipo específico de funcionalidad de software (como una biblioteca de matemáticas, que contendrá métodos previamente
probados para una variedad de funciones matemáticas que incluyen trigonometría, cálculo de raíces cuadradas, cálculos de
matrices y muchos más) o relacionados con la interfaz con un hardware específico. dispositivo, como una cámara de
seguridad (en cuyo caso la biblioteca tendría métodos para admitir acciones de panorámica, inclinación y zoom en la
cámara). Como ejemplo adicional, una biblioteca de cifrado de datos contendrá funciones para realizar el cifrado y también
para realizar el descifrado de datos.
Las bibliotecas son un requisito clave para gestionar la complejidad del desarrollo de software y también para
gestionar los costes de desarrollo, especialmente en términos de tiempo. Desarrollar todas las funciones desde cero
simplemente no es una opción realista en la mayoría de los proyectos. Como ejemplo de lo importantes y comunes
que son las bibliotecas, considere el programa muy simple de C ++ “Adder” que se vio por primera vez en el Capítulo
2; el código de este programa se muestra en Figura 5.27 .
Figura 5.27 ilustra el punto de que incluso los programas más simples se basan en bibliotecas. He escrito el
código para ingresar dos números; sumarlos y generar el resultado; esto fue muy fácil. Sin embargo, si tuviera que
escribir un programa que hiciera exactamente lo que he descrito, desde cero sin usar ningún código de biblioteca,
entonces sería una tarea más compleja. Mire de cerca la lista de códigos del programa y verá evidencia del uso de
una biblioteca. Aquí hay dos pistas específicas. En primer lugar, la declaración "#include <iostream>"

FIGURA 5.27

Un programa muy simple que usa una biblioteca.


5.13 BIBLIOTECAS DE SOFTWARE 337

indica que he incluido un archivo de encabezado C ++, que contiene las declaraciones de algunos
métodos; en este caso, están específicamente relacionados con el uso de los flujos de entrada y
salida (la forma en que operan se discutió en el Capítulo 2). La segunda pista es la declaración
"using namespace std" que indica al compilador que el conjunto de funcionalidades provisto
dentro del espacio de nombres (efectivamente biblioteca) llamado std puede ser usado, sin tener
que colocar "std ::" delante de cada llamada. Si se elimina esta declaración, el compilador se
queja del uso de los métodos cin y cout. Lo que está sucediendo aquí es que el archivo de
encabezado de iostream contiene las definiciones de los métodos cin y cout, y la implementación
real de estos se proporciona en la biblioteca std. En lugar de incorporar el espacio de nombres a
nivel de programa, Figura 5.28 .
Figura 5.28 proporciona una lista de código que es exactamente equivalente en lógica y función a la que se
muestra en Figura 5.27 , pero se ha modificado para enfatizar el uso del espacio de nombres estándar. El uso de esta
biblioteca es significativo porque los métodos cin y cout aparentemente inocuos esconden mucha complejidad que
no tengo tiempo para estudiar y replicar (y probar, en todo tipo de combinaciones de datos de entrada y salida) al
desarrollar mis aplicaciones. El uso de la biblioteca me ha ahorrado tiempo y ha hecho que mi código sea más
robusto.
Las bibliotecas son un concepto genérico compatible con casi todos los idiomas. Java proporciona un conjunto
completo de bibliotecas de clases estándar, la biblioteca de clases Java (JCL), que está organizada en forma de
paquetes (cada uno con un tema funcional específico, por ejemplo, programación de sockets o funciones de entrada
/ salida). Las declaraciones de "importación" se utilizan para señalar qué paquetes de biblioteca específicos se
utilizarán dentro de un programa en particular. La biblioteca de clases de .NET Framework es parte del Kit de
desarrollo de software (SDK) de Microsoft .NET Framework. Esta biblioteca es compatible con varios lenguajes
populares, incluidos Visual Basic, C # y C ++ / CLI (C ++ con Common Language Infrastructure). Para incorporar una
biblioteca en particular en un programa específico, Visual Basic usa la cláusula "Importa [nombre de la biblioteca]",
C # tiene la cláusula "usando [nombre de la biblioteca]",

# incluir "stdafx.h"
# incluir <iostream>

En t _tmain ( En t argc , _TCHAR * argv []) {

// Ingrese dos números del flujo de entrada


En t iFirstNumber;
En t iSecondNumber;
std :: cin >> iFirstNumber;
std :: cin >> iSecondNumber;

// Suma los números


En t iTotal = iFirstNumber + iSecondNumber;

// Envía el resultado al flujo de salida


std :: cout << iTotal;
regreso 0;
}

FIGURA 5.28

Énfasis en el uso de métodos bibliotecarios.


338 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Las bibliotecas pueden evolucionar junto con una aplicación. En particular, cuando se necesitan algunas partes de una
aplicación para su uso en otra aplicación, las partes comunes se pueden separar en una biblioteca. Esto no solo acelera en
gran medida el desarrollo de la segunda aplicación, sino que también garantiza la coherencia entre las funcionalidades
comunes de todas las aplicaciones que utilizan la biblioteca recién creada.
Las principales motivaciones para el uso de bibliotecas se pueden resumir de la siguiente manera:

• La necesidad de dividir el código en módulos con fines de desarrollo y prueba.


• La necesidad de reutilizar el código para reducir el tiempo de desarrollo y aumentar la solidez de las aplicaciones. La necesidad
• de reutilizar el código para lograr un comportamiento estandarizado. Por ejemplo, el uso de un método de una biblioteca
matemática estándar es más seguro desde el punto de vista de la corrección que un método desarrollado en casa. Para un
segundo ejemplo, el uso de las mismas bibliotecas de interfaz de usuario en un conjunto de aplicaciones permite mantener una
apariencia coherente de las aplicaciones.
• La necesidad de poder soportar variantes de aplicaciones. Por ejemplo, para lograr la misma funcionalidad de lógica
empresarial en varias versiones de una aplicación que utilizan diferentes dispositivos de E / S, solo se pueden
intercambiar las bibliotecas relacionadas con E / S, lo que minimiza la interrupción del código a nivel de la aplicación.

La necesidad de refactorización. Es típico que la primera versión funcional de un programa no sea óptima en términos de
estructura clara y brevedad del código. Un buen análisis de los requisitos y las etapas de diseño del ciclo de vida ayudan a
definir una buena estructura básica, pero por lo general hay espacio para el refinamiento. Las razones comunes para la
refactorización son agrupar métodos relacionados (aquellos que realizan funciones relacionadas o manipulan el mismo
conjunto de datos) en nuevas clases y también subdividir métodos grandes en otros más pequeños, haciendo que el código
sea más modular y legible y, por lo tanto, más fácil de mantener.
La duplicación de código no es deseable porque aumenta el volumen de un programa, no solo lo hace más difícil de verificar y probar, sino

que también reduce la legibilidad. Además, si una función en particular se repite varias veces en el mismo programa y se necesita un cambio en

esa funcionalidad, el cambio debe realizarse de la misma manera en todas las secciones duplicadas; esto es costoso y propenso a errores. La

refactorización se realiza a menudo para eliminar secciones duplicadas de código. Por ejemplo, suponga que hay una pequeña sección de tres

líneas de código que realiza un cálculo en particular dentro de una aplicación. Este cálculo es necesario en tres partes diferentes de la lógica del

programa, por lo que el desarrollador original había copiado la sección de tres líneas ya probada en los dos lugares adicionales del código. Si la

naturaleza del cálculo cambia (considere una aplicación de contabilidad, manteniéndose actualizada de acuerdo con la legislación

gubernamental y las reglas fiscales cambiantes), entonces es necesario cambiar el código. Los errores difíciles de detectar aparecerán a menos

que las tres copias de la función se actualicen de manera idéntica. La refactorización resuelve este problema colocando la sección crítica de

código de tres líneas en un nuevo método con un nombre significativo que describe sucintamente lo que hace el método. A continuación, se

llama al nuevo método desde los tres lugares del programa donde se ubicaron las tres copias del código. De esta forma, se elimina la

duplicación. Los errores difíciles de detectar aparecerán a menos que las tres copias de la función se actualicen de manera idéntica. La

refactorización resuelve este problema colocando la sección crítica de código de tres líneas en un nuevo método con un nombre significativo que

describe sucintamente lo que hace el método. A continuación, se llama al nuevo método desde los tres lugares del programa donde se ubicaron

las tres copias del código. De esta forma, se elimina la duplicación. Los errores difíciles de detectar aparecerán a menos que las tres copias de la función se actualicen de m

5.13.1 EJEMPLO DE CASO DE BIBLIOTECA DE SOFTWARE

La aplicación de intercambio de medios peer-to-peer se utilizará como ejemplo de caso para la creación de una
biblioteca de software. Este ejemplo de caso abordará la tarea de crear una biblioteca de software utilizando una
aplicación real con la que los lectores estarán familiarizados y siguiendo la misma secuencia típica de pasos que
seguiría un desarrollador de software.
5.13 BIBLIOTECAS DE SOFTWARE 339

Un desarrollador de software experimentado verá el código de la aplicación de una manera diferente a como lo ve un
novato. El código de muestra original para la aplicación de intercambio de medios de igual a igual proporciona un buen
ejemplo. Un principiante puede mirar el código y contentarse con el hecho de que los diversos métodos y variables tienen
nombres significativos para que el código sea fácil de entender (estas características se denominan "características de
autodocumentación" y deben ser parte de la práctica diaria). Donde se necesita más explicación, se han agregado
comentarios al código fuente. Estos contienen suficientes detalles para explicar cualquier funcionalidad compleja o para dar
al lector una pista de por qué una sección particular de código fue diseñada de cierta manera o quizás por qué una
secuencia de pasos se lleva a cabo en un orden particular. Sin embargo, también es importante no tener demasiados
comentarios; de lo contrario, los importantes no se destacan y la legibilidad del código disminuye en lugar de aumentar.
Cuando ejecutan el código, funciona como esperan (por haber estudiado el código) y así el desarrollador novato queda
satisfecho.
Sin embargo, un desarrollador de software experimentado miraría el código y pensaría que necesita una
"refactorización", lo que básicamente significa que hay oportunidades para mejorar la estructura del código
dividiéndolo en métodos adicionales y posiblemente incluso creando clases adicionales. Para poner esto en
contexto, parte del código de la aplicación se muestra en Figura 5.29 .
Figura 5.29 muestra una muestra del código fuente original de la aplicación MediaShare_Peer. Se han seleccionado tres
secciones de código (en cada caso separadas por una línea de tres puntos) para ilustrar la forma en que la funcionalidad
relacionada con la gestión de datos de descubrimiento de pares se fusionó en la clase de aplicación principal en la versión
original de la aplicación MediaShare_Peer.

[Link] Breve descripción del código original


La primera sección de código que se muestra en Figura 5.29 muestra el formato de la estructura de datos utilizada para
contener detalles de cada par descubierto. Los pares se identifican por su dirección IP y número de puerto (la estructura
SOCKADDR_IN), combinados con una ID elegida al azar, que se genera al inicio del proceso. El indicador InUse es necesario
porque una lista de estas estructuras se mantiene dinámicamente y es importante que los detalles de un par recién
descubierto no sobrescriban una instancia de la matriz utilizada actualmente (considere el comportamiento de la función de
descubrimiento de pares cuando hay muchos pares que se unen y salir de la aplicación de forma dinámica). La bandera
MediaDataReceived se utiliza para que a cada par conocido solo se le soliciten detalles de sus recursos multimedia hasta que
los haya proporcionado.
La siguiente sección de código muestra cinco métodos que están relacionados con el mantenimiento y el acceso
a los datos relacionados con la lista de pares conocidos. Esta es una subárea muy importante de funcionalidad de la
aplicación; los datos relacionados con pares conocidos se utilizan no solo en el comportamiento de descubrimiento
de pares, sino también en la lógica que controla el envío de mensajes y el procesamiento de los mensajes recibidos.

La tercera sección de código que se muestra en Figura 5.29 muestra un ejemplo de la forma en que se utilizan los datos
relacionados con los pares conocidos en el envío de uno de los tipos de mensaje: REQUEST_MEDIA_LIST. En primer lugar, el
índice de la entrada de datos para el par objetivo en particular se recupera de la matriz de estructuras a través de uno de los
métodos GetIndexOf_KnownPeer_InPeersList (que se muestra en la sección de código anterior) utilizando el ID del par como
término de búsqueda. La dirección del par objetivo se recupera de la matriz de estructuras, y se accede directamente
utilizando la posición del índice del par en la lista. Más adelante, en la misma sección de código, se accede directamente a
los datos de la matriz cuando se proporciona un resultado de diagnóstico que indica la dirección y el número de puerto al
que se envió el mensaje.
El código del programa completo para la aplicación MediaShare_Peer está disponible como parte de los recursos que
acompañan al libro.
340 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

FIGURA 5.29

Secciones del código fuente original de la aplicación de intercambio de medios peer-to-peer.


5.13 BIBLIOTECAS DE SOFTWARE 341

[Link] Ejemplo de refactorización para la aplicación MediaShare_Peer


Se realiza una refactorización parcial de la aplicación MediaShare_Peer para ilustrar algunos de los conceptos de
refactorización en la práctica. La refactorización se centra en la funcionalidad asociada con la gestión de datos de
descubrimiento de pares, como se muestra en Figura 5.29 . La refactorización también sirve como paso previo a la
separación del código en una parte específica de la aplicación y una biblioteca de software que puede ser reutilizada
por otras aplicaciones que tienen requisitos similares con respecto al descubrimiento dinámico de pares.

Los pasos dados para este ejercicio de refactorización en particular fueron los siguientes:

1. Identifique un grupo de métodos que estén relacionados en términos de la funcionalidad que realizan y también en términos de
los elementos de datos que manipulan.
2. Cree una nueva clase llamada CKnownPeers.
3. Mueva los métodos identificados a la nueva clase. Mueva el elemento de datos específico de la clase (la matriz de
estructuras KnownPeers) a la nueva clase, como una variable miembro.
4. Asigne la nueva clase CKnownPeers a la lógica de la aplicación restante, realizando llamadas al
constructor y métodos de la nueva clase para reemplazar el acceso directo anterior a los elementos
de datos.
5. Pruebe con cuidado; las versiones anteriores y posteriores a la fabricación de la aplicación deben tener un comportamiento
idéntico en el nivel de la aplicación. Tenga en cuenta que la refactorización no está destinada a cambiar el comportamiento ni a
corregir errores, por lo que, aunque la arquitectura interna del código haya cambiado, la funcionalidad empresarial no debería
hacerlo. Si hay diferencias resultantes en el comportamiento, entonces la refactorización es incorrecta.

Figura 5.30 contiene dos secciones del código de la nueva clase creada en el proceso de refactorización, y las secciones
están separadas por una fila de tres puntos. La primera sección de código es la definición de clase del archivo de
encabezado C KnownPeers.h. Esto define la clase en términos de sus funciones miembro y elementos de datos. Zcore al
funcionamiento de esta clase. La segunda sección de código muestra parte de la implementación de la clase. Se incluye el
archivo de encabezado de clase, seguido de las definiciones de dos de los métodos de clase, siendo el primero de ellos el
constructor.
Figura 5.31 muestra algunos aspectos del mapeo entre las dos clases. La clase de aplicación principal todavía
contiene la lógica específica de la aplicación. Esta clase contiene una variable miembro m_pKnownPeers, que en
realidad es una instancia de objeto de la nueva clase CKnownPeers (consulte la primera sección de código en la
figura). El m_pKnownPeers se inicializa llamando al constructor de la clase dentro del constructor de la clase externa
(la segunda sección de código en la figura). A partir de este punto, se pueden llamar a los métodos del objeto
m_pKnownPeers.
La tercera sección de código en Figura 5.31 muestra la nueva versión del método DoSend_REQUEST_MEDIA_
LIST_To_NewlyDiscoveredPeer, que usa los métodos de la nueva clase para acceder indirectamente a los datos de
KnowPeers; las apariciones de la variable m_pKnownPeers han sido resaltadas (compare con la versión que se
muestra en Figura 5.29 ).

[Link] Ejemplo de biblioteca para la aplicación MediaShare_Peer


El código común (que es utilizado por varias aplicaciones) o el código con alguna funcionalidad limitada específica
se puede extraer del código de la aplicación en una biblioteca. Es muy importante que la separación entre el código
específico de la aplicación y el código de la biblioteca se realice a lo largo de un límite claro y no debe traspasar las
clases, por ejemplo.
342 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

FIGURA 5.30

La nueva clase CKnownPeers extraída mediante refactorización.

La refactorización descrita anteriormente ha creado una clase adicional con funcionalidad especializada asociada con la
gestión de datos de descubrimiento de pares. Esta funcionalidad se diferencia claramente de la funcionalidad específica de
la aplicación que permanece en la clase de aplicación principal y es potencialmente útil para muchas aplicaciones, por lo que
es un candidato ideal para la separación en una biblioteca de software para promover la reutilización.

Desde este punto de partida, la creación de una biblioteca de software es sencilla. En primer lugar, se crea un
nuevo proyecto de software y la nueva clase se mueve del proyecto original al nuevo. El compilador debe
configurarse para crear una biblioteca en lugar de una aplicación ejecutable. Esto es importante debido a la forma
en que se utilizará el archivo de biblioteca resultante. No tiene su propio punto de entrada, por ejemplo, por lo que
no se puede ejecutar como un proceso separado. En cambio, la biblioteca se vinculará a las aplicaciones después de
que se haya compilado su propio código.
5.13 BIBLIOTECAS DE SOFTWARE 343

FIGURA 5.31

Mapeo entre la clase de aplicación principal y la clase KnownPeers.

La biblioteca se compila, creando un archivo con extensión .lib. Para el ejemplo específico que se describe aquí,
el nombre del archivo es DemonstrationLibrary_for_MediaShare_Peer.lib (el proyecto y los códigos fuente están
disponibles como parte de los recursos que acompañan al libro).
El proyecto de la aplicación ya no contiene la funcionalidad de la clase CKnownPeers que se trasladó a la biblioteca. Por
lo tanto, el proyecto de la aplicación debe vincularse a la biblioteca; esto se logra configurando la biblioteca como un archivo
de entrada (dependencia) del proyecto en la configuración del vinculador.
Figura 5.32 proporciona una representación resumida de la secuencia de etapas descritas anteriormente, lo que da como
resultado un componente de biblioteca de software que se puede vincular a una o más aplicaciones.
Es importante reforzar el mensaje de que las tres versiones de la aplicación tienen el mismo comportamiento
externo. La lógica de la aplicación se ha redistribuido entre las clases y componentes de software, pero el
comportamiento es idéntico en cada caso. Para confirmar esto, se probó la interoperabilidad de las versiones,
ejecutando simultáneamente pares de las diferentes versiones. Puede repetir la prueba cruzada de esta versión
usted mismo, ya que todas las versiones del código están disponibles en los recursos adjuntos.
344 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Clave:

1. La versión original de la aplicación constaba de


C un único componente de software. La lógica de la Clase C
aplicación estaba contenida en una sola clase.
Componente

Proceso
2. La versión refactorizada dividió la lógica del programa
en una clase específica de aplicación y una clase de
C1C2 soporte. Las clases se integran en tiempo de compilación.
El componente de software único se ejecuta como un
proceso único

3. La versión de la biblioteca consta de dos componentes


del programa de software que se compilan por separado y
C1 C2 luego se vinculan para crear una aplicación ejecutable (que
Solicitud- Apoyo se ejecuta como un solo proceso).
lógica específica Biblioteca

4. El componente de la biblioteca se puede reutilizar con


C3 C2 otras aplicaciones que requieren la misma funcionalidad de
Solicitud- Apoyo soporte que proporciona la biblioteca.
lógica específica Biblioteca

FIGURA 5.32

Representación esquemática de las etapas de creación y uso de la biblioteca.

5.13.2 ENLACE ESTÁTICO Y ENLACE DINÁMICO


Las bibliotecas están vinculadas al código fuente de la aplicación de dos formas principales: estáticamente, donde la vinculación se
realiza en la etapa de compilación del componente (por lo general, esto es inmediatamente después de la compilación) y se crea un
ejecutable autónomo y, dinámicamente, donde la vinculación se pospone para ejecutarse tiempo (la vinculación se realiza cuando el
componente se ejecuta como un proceso).

[Link] Enlace estático


La vinculación estática se realiza cuando se crea un componente de software (es decir, cuando se crea el archivo ejecutable).
El compilador verifica la sintaxis del código y crea una representación de código intermedio del programa. El enlazador
luego incluye todo el código de biblioteca necesario en la imagen binaria (el archivo ejecutable). Esto puede aumentar
significativamente el tamaño del archivo ejecutable resultante, aunque muchos enlazadores optimizados solo agregan los
fragmentos de código realmente usados de la biblioteca (solo las implementaciones de los métodos realmente
referenciados en el código fuente de la aplicación).

[Link] Vinculación dinámica


El enlace dinámico se realiza en tiempo de ejecución y utiliza una variación especial de un formato de biblioteca llamado
biblioteca de enlace dinámico (DLL). Este enfoque es muy popular entre los sistemas operativos de Microsoft y llegó a limitar
el tamaño de los archivos ejecutables de la aplicación y también sus imágenes en tiempo de ejecución. El enfoque es
ventajoso cuando varias aplicaciones se ejecutan en el mismo sistema y requieren la misma biblioteca, porque
5.13 BIBLIOTECAS DE SOFTWARE 345

el sistema operativo lee el archivo DLL en la memoria y guarda su imagen, por separado de las imágenes de los dos
o más procesos de aplicación, de modo que cada uno pueda llamar a secciones de código de la biblioteca según sea
necesario. Cuantas más aplicaciones utilicen la misma DLL, más ahorro de memoria se hará. Sin embargo, si solo
una aplicación usa la DLL, no hay ahorro de espacio porque el tamaño combinado del archivo ejecutable de la
aplicación y el archivo DLL ocupará aproximadamente el mismo espacio en el almacenamiento secundario (como el
disco duro) que la única. aplicación con la biblioteca estática preenlazada. Además, dado que ambas partes deben
mantenerse en la memoria en tiempo de ejecución, requerirán aproximadamente la misma memoria combinada
que el proceso equivalente vinculado estáticamente.

[Link] Compensación entre bibliotecas estáticas y dinámicas


El archivo ejecutable es más grande cuando se usa un enlace estático que con un enlace dinámico. La diferencia de tamaño puede ser
significativa para aplicaciones grandes y afecta los requisitos de espacio de almacenamiento, el tiempo necesario para transmitir el
archivo a través de una red y también la cantidad de tiempo necesario para cargar el archivo como primer paso en la ejecución.

El tamaño de la imagen de la memoria es mayor para los procesos en los que las bibliotecas se han vinculado
estáticamente; sin embargo, un proceso que utiliza enlaces dinámicos aún necesita acceso al código de la biblioteca. Por lo
tanto, la DLL también debe cargarse en la memoria, igualando las ganancias cuando es utilizada por un solo proceso, pero
potencialmente ahorrando mucho espacio de memoria cuando muchas aplicaciones comparten la misma imagen de DLL.
La vinculación dinámica se puede utilizar para lograr la configurabilidad en el momento de la implementación, en la que hay diferentes

versiones de la misma DLL pero con diferentes funcionalidades. Los nombres de los métodos en la biblioteca serán los mismos, de modo que el

código de la aplicación se pueda vincular con cualquiera de las versiones y funcionar correctamente. Esto luego permite cierto control sobre la

forma en que opera la aplicación al cambiar qué versión de la DLL está presente y sin cambiar el código de la aplicación o la imagen ejecutable.

Sin embargo, el control de versiones de DLL puede ser problemático. La mayoría de las aplicaciones se publican como versiones de compilación

particulares, que se han probado cuidadosamente y se considera que son estables; por ejemplo, es posible que se publique una nueva versión

después de que se hayan realizado algunas actualizaciones. Del mismo modo, las DLL pueden actualizarse y también tener números de versión.

Tener dos tipos de componentes interdependientes (una aplicación y una DLL) que se versionan por separado a lo largo del tiempo puede dar

lugar a desajustes complejos en el tiempo de ejecución. Si el nombre de un método en uno de los componentes ha cambiado, o el conjunto de

parámetros pasados es diferente, entonces la aplicación no se ejecutará o puede fallar cuando se realiza la llamada del problema. Si los cambios

se refieren solo a la lógica dentro de un método de biblioteca, entonces la aplicación puede parecer que funciona correctamente pero devuelve

un resultado incorrecto. Para poner el problema en contexto, considere una aplicación que tiene una versión inicial 1.1, que funciona

perfectamente con su DLL versión 1.1. Después de algunos meses, ha habido tres versiones más de la aplicación (versiones 1.2, Si el nombre de

un método en uno de los componentes ha cambiado, o el conjunto de parámetros pasados es diferente, entonces la aplicación no se ejecutará

o puede fallar cuando se realiza la llamada del problema. Si los cambios se refieren solo a la lógica dentro de un método de biblioteca, entonces la aplicación puede pa

1.3 y 2.0) y cinco versiones más de la DLL (versiones 1.2, 1.3a, 1.3b, 2.0 y 2.1). Es muy probable
que haya numerosas combinaciones que funcionen bien, algunas que aún no se han producido,
por lo que se desconoce el resultado (pero se considera inseguro) y algunas que definitivamente
no funcionan. Si agrega al escenario la existencia de cientos de sitios de clientes, cada uno con
sus propios equipos técnicos que realizan actualizaciones del sistema, puede comenzar a ver
algunos aspectos de los desafíos de control de versiones que pueden ocurrir con proyectos de
software de componentes múltiples. La posibilidad de tales problemas aumenta la carga de la
prueba, para garantizar que las imágenes del sistema implementadas contengan solo
combinaciones válidas de los componentes.
La DLL puede omitirse de una computadora de destino. De manera similar al problema anterior, los requisitos
de DLL externos de las aplicaciones deben tenerse en cuenta al instalar las aplicaciones. Frustrante
346 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

La situación surge cuando la aplicación se ejecuta perfectamente en la computadora de desarrollo (que obviamente tiene la
DLL presente) pero luego no se ejecuta cuando se transfiere a otra computadora porque la DLL no está presente en ese
sitio. Esta situación suele ser fácil de solucionar a pequeña escala, pero aumenta el costo general del mantenimiento de los
sistemas.
Las aplicaciones vinculadas estáticamente son autónomas; el código de la biblioteca se ha fusionado para crear un único
archivo ejecutable sin dependencias externas. Esto es sólido porque evita los problemas de omisión de DLL o falta de
coincidencia de la versión de DLL.

5.13.3 FUNCIÓN DEPENDIENTE DEL IDIOMA: EL ARCHIVO DE ENCABEZADO C / C ++

Los lenguajes C y C ++ tienen un tipo de archivo de encabezado, así como el tipo de archivo de código fuente. El uso del tipo
de archivo de encabezado puede mejorar la arquitectura del código interno de los componentes individuales y ayudar a
garantizar la coherencia entre varios componentes de una aplicación distribuida; por lo tanto, se incluye en este capítulo.
El archivo de encabezado se usa para contener definiciones de cosas, a diferencia de los detalles de implementación. El código C
++ bien estructurado se dividirá en varias clases, cada clase tendrá un archivo fuente (con
una extensión de nombre de archivo .cpp) y un archivo de encabezado (con una extensión de nombre de archivo .h). El archivo de
encabezado de clase contendrá la definición de la clase y sus métodos y declarará cualquier variable miembro a nivel de clase. El
archivo de encabezado de clase también puede contener las definiciones de constantes, estructuras, enumeraciones y otras
construcciones utilizadas en la clase. También puede haber archivos de encabezado adicionales, es decir, aquellos que no están
relacionados con ninguna clase específica. Estos pueden ser parte del lenguaje en sí (por ejemplo, relacionados con el uso de
bibliotecas, como con el encabezado afxsock.h representado en Figura 5.34 , necesario porque la aplicación usa la biblioteca de
sockets) o puede contener definiciones de toda la aplicación que se usan en varios componentes. Figura 5.33
ilustra la forma en que los archivos de encabezado se pueden usar para múltiples propósitos en una aplicación.
Figura 5.33 ilustra algunos usos comunes de los archivos de encabezado para proporcionar estructura al código fuente de una aplicación

distribuida. Los archivos de encabezado de la biblioteca de idiomas se relacionan con la inclusión de rutinas de biblioteca (por ejemplo, la

biblioteca de API de sockets); contienen las declaraciones de las rutinas, que el compilador necesita en el momento de la compilación para poder

comprobar la sintaxis. Por ejemplo, aunque el compilador no vincula las bibliotecas reales, debe asegurarse de que los diversos métodos que se

han utilizado desde una biblioteca en particular se hayan utilizado correctamente, con la sintaxis adecuada, el número y los tipos de parámetros

necesarios, etc. Los archivos de encabezado específicos de los componentes proporcionan las definiciones para las clases de implementación (la

funcionalidad específica de la aplicación). Los encabezados de toda la aplicación se pueden usar para proporcionar definiciones globales que se

compilan en cada uno de los componentes y, por lo tanto, son muy importantes para garantizar la coherencia en las formas en que se

comportan ciertos componentes relacionados. Un buen ejemplo de esto es el

Idioma- Componente- Solicitud- Componente- Idioma-


Biblioteca específico amplio específico Biblioteca

encabezados encabezados encabezados encabezados encabezados

ComponenteA Componente B

FIGURA 5.33

Uso de archivos de encabezado al crear aplicaciones distribuidas.


5.13 BIBLIOTECAS DE SOFTWARE 347

definición de tipos de mensajes y formatos de mensajes (PDU; consulte el Capítulo 4) que deben ser los mismos para cada
componente para que los mensajes se interpreten correctamente. En la aplicación que se muestra en Figura 5.33 , cada uno
de los componentes A y B se compilará por separado, pero se usarán los mismos archivos de encabezado de toda la
aplicación en ambas compilaciones.
Figura 5.34 coloca el uso de archivos de encabezado en un escenario de caso de uso específico, utilizando la aplicación
de base de datos de tres niveles discutida y utilizada en Actividad A1 más temprano. Para cada componente, solo se muestra
el nombre de la clase principal para evitar una complejidad innecesaria, pero de lo contrario, esta figura refleja con precisión
la arquitectura del software a nivel de componente. La aplicación consta de tres componentes de software diferentes
(cliente de aplicación, servidor de aplicación y servidor de base de datos), cada uno de los cuales se compila en un archivo
ejecutable independiente y se ejecuta como un proceso independiente. Dado que los tres componentes son parte de la
misma aplicación, deben tener definiciones inequívocas de formatos de mensaje, identificadores de tipo de mensaje y
números de puerto de aplicación predefinidos. Esto se logra colocando estas definiciones en el archivo DB_Arch_General.hy
incluyéndolo en las tres compilaciones. El contenido de este archivo de encabezado se muestra en Figura 5.35 .

DB_Arch_General.h

afxsock.h DB_Arch_App DB_Arch_App afxsock.h DB_Arch_DB afxsock.h


(y otros) ClientDlg.h ServerDlg.h (y otros) ServerDlg.h (y otros)

Cliente (nivel 1) Servidor de aplicaciones (nivel 2) Servidor de base de datos (nivel 3)

La clase principal es DB_Arch_AppClientDlg La clase principal es DB_Arch_AppServerDlg La clase principal es DB_Arch_DBServerDlg

FIGURA 5.34

Ejemplo de uso de archivo de encabezado, una aplicación de base de datos de tres niveles.

FIGURA 5.35

El contenido del archivo de encabezado DB_Arch_General.h de Figura 5.34 .


348 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

El contenido del archivo de encabezado de toda la aplicación DB_Arch_General.h se muestra en Figura 5.35 .
Este archivo proporciona definiciones importantes que deben ser coherentes para todos los componentes de la aplicación.
Si se agrega un nuevo tipo de mensaje a la aplicación para ampliar la funcionalidad, agregarlo a la enumeración
proporcionada en este archivo de encabezado garantizaría que se defina de la misma manera para todos los componentes.
De manera similar, si el nuevo tipo de mensaje también requiere que se agregue un campo adicional a la PDU del mensaje,
agregarlo en la estructura definida aquí tendrá un efecto en toda la aplicación.

5.14 VIRTUALIZACIÓN DE HARDWARE


Para explicar la virtualización de hardware de una manera clara y accesible, primero es necesario revisar
brevemente los conceptos de computación no virtualizada (algunos pueden decir “tradicional”).
El modelo no virtualizado de computación es que cada computadora tiene un sistema operativo instalado y el sistema operativo tiene un

componente programador que ejecuta procesos, de modo que los procesos pueden usar los recursos de la computadora (este aspecto se

discutió en profundidad en el Capítulo 2). El sistema operativo oculta algunos aspectos de la configuración de la plataforma de hardware. Un

aspecto muy importante de esto es la administración de recursos que se realiza para garantizar que los recursos se utilicen de manera eficiente

(por ejemplo, a cada proceso solo se le puede dar acceso a una fracción particular de todo el espacio de memoria del sistema, lo que permite que

múltiples procesos se ejecuten simultáneamente sin interferencia) . El sistema operativo también aísla los procesos de aplicación de los

dispositivos físicos, Un ejemplo particular que se analizó en el Capítulo 2 fue la forma en que el sistema operativo gestiona los flujos de entrada y

salida para que los procesos no manipulen directamente los dispositivos IO. Esta gestión del sistema operativo de los dispositivos tiene dos

ventajas importantes, una es que los diversos dispositivos IO pueden ser utilizados por múltiples procesos sin conflicto y la otra es que los

detalles específicos de la interfaz de los dispositivos IO individuales se abstraen en el nivel del programa. Entonces, por ejemplo, un

programador puede escribir una declaración de entrada o salida sin saber el tipo o tamaño de pantalla, el tipo de teclado, etc., que está presente

y también el programa una vez escrito funcionará correctamente incluso si se cambian los dispositivos IO en el futuro. Esta gestión del sistema

operativo de los dispositivos tiene dos ventajas importantes, una es que los diversos dispositivos IO pueden ser utilizados por múltiples procesos

sin conflicto y la otra es que los detalles específicos de la interfaz de los dispositivos IO individuales se abstraen en el nivel del programa.

Entonces, por ejemplo, un programador puede escribir una declaración de entrada o salida sin saber el tipo o tamaño de pantalla, el tipo de teclado, etc., que está presente

La virtualización de hardware es el término que se utiliza para describir la adición de una capa de software, que se
encuentra en la plataforma de hardware real y actúa como si en realidad fuera la propia plataforma. La capa de software se
llama máquina virtual. La VM es capaz de ejecutar procesos de la misma manera que lo haría el sistema operativo en el
modelo tradicional (no virtualizado) de computación descrito anteriormente.
De alguna manera, la virtualización de hardware puede considerarse una extensión de los aspectos de aislamiento y
transparencia que los sistemas operativos brindan a los procesos. Sin embargo, la virtualización de hardware está motivada
por la necesidad de admitir la reasignación flexible y la reconfiguración de computadoras, lo que puede implicar reemplazar
toda la imagen del software en la computadora, incluido el sistema operativo (o ejecutar dos sistemas operativos diferentes
en la misma computadora) y realizar estos cambios. en un corto período de tiempo.
Para apreciar la importancia de la flexibilidad adicional que representa el enfoque VM, sobre el enfoque no
virtualizado, es necesario considerar los altos grados de heterogeneidad que ocurren en los sistemas distribuidos
modernos. La heterogeneidad se manifiesta de muchas formas, como se discutió anteriormente en este capítulo. La
existencia de tantas plataformas de hardware, sistemas operativos y configuraciones de recursos diferentes añade
mucha complejidad a la gestión de los sistemas informáticos. Los usuarios necesitan ejecutar una variedad de
aplicaciones que pueden requerir una configuración diferente de recursos o incluso diferentes sistemas operativos,
sin embargo, no es factible reinstalar el sistema operativo para ejecutar una aplicación en particular o proporcionar
a cada usuario varias computadoras configuradas de manera diferente en orden para permitirles ejecutar el
5.14 VIRTUALIZACIÓN DE HARDWARE 349

varias aplicaciones diferentes que necesitan a lo largo de la jornada laboral. El problema es más significativo para los
propietarios de recursos informáticos a gran escala debido al costo de compra de equipos y los costos de administración en
curso potencialmente aún mayores asociados con la mano de obra necesaria para ayudar a los usuarios con tales requisitos.
Los centros de datos, en particular, necesitan una forma de tratar automáticamente los problemas de heterogeneidad,
porque alquilan sus recursos informáticos a numerosos clientes diferentes, por lo que multiplican el número de
configuraciones de recursos diferentes que probablemente sean necesarias. Claramente, los centros de datos no pueden
satisfacer esta demanda de manera rentable y oportuna con plataformas físicas configuradas específicamente porque
tendrían que tener un número total de computadoras mucho mayor y un equipo de soporte técnico muy grande.

5.14.1 MAQUINAS VIRTUALES


Las máquinas virtuales se han convertido en una herramienta esencial para superar el desafío de la frecuente reconfiguración de
plataformas para satisfacer las diversas necesidades de los usuarios, que surgen en parte de las diversas formas de heterogeneidad
en los sistemas modernos y también debido a la gran variedad de aplicaciones de la computación con cada vez más. creciente
extensión de funcionalidad y la inevitable complejidad que la acompaña.
Una máquina virtual es un proceso que se ejecuta en la computadora física y presenta una interfaz para el proceso de la
aplicación, que imita la de la computadora real. Por tanto, la máquina virtual aísla los procesos de aplicación de la máquina
física. Por ejemplo, una computadora que ejecuta un sistema operativo en particular (como Microsoft Windows) puede
albergar una VM que emula una computadora que ejecuta un sistema operativo diferente, como Linux, en cuyo caso las
aplicaciones de Linux se ejecutarán en la VM y se comportarán de la misma manera. como si estuviera en una computadora
real con el sistema operativo Linux genuino instalado. La máquina virtual es el proceso con el que se ocupa el programador
de Windows; ver Figura 5.36 .
Figura 5.36 muestra cómo se puede ejecutar una máquina virtual sobre un sistema operativo convencional como Microsoft
Windows, para permitir la ejecución de aplicaciones no nativas. En otras palabras, la VM proporciona una emulación de un sistema
operativo diferente (Linux en este caso) y, por lo tanto, permite que se ejecuten aplicaciones diseñadas para ese sistema operativo.

Para entornos en los que las computadoras deben configurarse con diferentes VM, se puede utilizar un administrador
de VM o un hipervisor. El hipervisor crea y ejecuta máquinas virtuales según sea necesario. La necesidad de una gestión de
VM automatizada puede entenderse considerando un escenario de centro de datos: cada cliente en particular desea
ejecutar su aplicación específica, que requiere un determinado sistema de tiempo de ejecución (es decir, el sistema
operativo y varios servicios necesarios). En lugar de tener que aprovisionar la computadora para cada cliente

Proceso de usuario
Entidad ejecutable
(Linux
solicitud) visto por VM

Entidad programable como Proceso de usuario


visto por el sistema Emulación de VM de Linux
(Ventanas
sistema operativo
operativo Windows solicitud)

Sistema operativo Windows

Plataforma de hardware

FIGURA 5.36

Usar una máquina virtual para emular sistemas operativos adicionales en una sola computadora.
350 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

instalando el sistema operativo apropiado y luego cada uno de los servicios requeridos y luego los diversos
componentes de la aplicación específica del cliente, que involucra muchas etapas separadas y, por lo tanto, requiere
mucho tiempo y está sujeto a fallas en los pasos individuales, el hipervisor puede generar la imagen de VM
adecuada en un solo paso.
Los hipervisores de tipo 1 se ejecutan directamente en el hardware de la computadora (es decir, reemplazan el sistema operativo), mientras

que los hipervisores de tipo 2 están alojados en un sistema operativo (es decir, se ejecutan en la parte superior del sistema operativo de la

misma manera que la VM se ejecuta en la parte superior). del sistema operativo en Figura 5.36 ).

5.14.2 MÁQUINA VIRTUAL DE JAVA


Java implementa una máquina virtual específica, la JVM, que ofrece una interfaz coherente para los programas de Java
independientemente del sistema operativo y la arquitectura reales. Los programas Java realmente se ejecutan en la JVM y no
directamente en la plataforma subyacente; esto significa que los programas Java son inherentemente portátiles. Este
concepto se ilustra con la ayuda de Figuras 5.37 y 5.38 .

Entidad programable
visto por Proceso de usuario Proceso de usuario
sistema operativo
Proceso de interfaz a M Proceso de interfaz a N
(no estándar) (no estándar)

Sistema operativo tipo M Tipo de sistema operativo N

Interfaz M-a-A Interfaz N-to-B

Plataforma de hardware tipo A Plataforma de hardware tipo B

FIGURA 5.37

La interfaz convencional de proceso a sistema operativo depende del sistema operativo.

Proceso de usuario Proceso de usuario


Entidad programable
visto por Proceso de interfaz a JVM Proceso de interfaz a JVM
sistema operativo (estándar) (estándar)

JVMtype Y JVMtype Z

Interfaz Y-to-M Interfaz Z-to-N

Sistema operativo tipo M Sistema operativo tipo N

Interfaz M-a-A Interfaz N-to-B

Plataforma de hardware tipo A Plataforma de hardware tipo B

FIGURA 5.38

La interfaz estándar de JVM para procesos.


5.15 CONFIGURACIONES ESTÁTICAS Y DINÁMICAS 351

Figura 5.37 muestra que el entorno de tiempo de ejecución del proceso convencional (la interfaz del proceso al sistema
operativo) es proporcionado de manera diferente por cada sistema operativo (como se explica en detalle en Sección 5.3
más temprano). Esto significa que las aplicaciones deben crearse específicamente para su sistema operativo de destino y,
por lo tanto, los ejecutables no se pueden transferir entre sistemas operativos.
Figura 5.38 muestra que la JVM proporciona una interfaz estándar para los procesos de la aplicación,
independientemente del sistema subyacente que comprenda cualquier combinación de sistema operativo y plataforma de
hardware. Esto se logra mediante el uso de un formato de código universal especial llamado código de bytes de Java, que es
una representación simple y estandarizada de la lógica del programa con un formato de bajo nivel que es similar al lenguaje
ensamblador en algunos aspectos. El resultado final es que el proceso del usuario en la parte izquierda de Figura 5.38 funcionará
correctamente en el sistema que se muestra a la derecha de Figura 5.38 sin ninguna modificación o recompilación.
La JVM en sí tiene que construirse específicamente para la plataforma en la que se ejecuta, de ahí las
diferencias en el tipo de JVM y la interfaz del sistema operativo con la JVM (la capa debajo de la JVM), en Figura
5.38 . El sistema operativo ve a la JVM como la entidad programable; en otras palabras, la JVM en sí es el
proceso que se ejecuta directamente sobre el sistema operativo y no la aplicación Java.

5.15 CONFIGURACIONES ESTÁTICAS Y DINÁMICAS


El tema de las configuraciones de software estáticas versus dinámicas se ha abordado en varias secciones anteriores, que
incluyen Sección 5.5.1 y tambien en Sección 5.9 donde se discutieron y exploraron configuraciones de aplicaciones ad hoc en
una actividad. Más adelante en este capítulo, Sección 5.16.1 también examina la configuración dinámica de un servicio para
enmascarar el fallo de una instancia de servidor individual.
Esta sección reúne los diversos problemas asociados con la elección entre configuraciones estáticas y
dinámicas de aplicaciones distribuidas. Los principales aspectos que deben tenerse en cuenta son la forma
en que los componentes se ubican entre sí, la forma en que los componentes forman conexiones o al menos
se comunican entre sí, y la forma en que los roles se asignan a los componentes individuales de un grupo (p.
Ej., cuando hay varias instancias de un servicio y se necesita un solo coordinador).

5.15.1 CONFIGURACIÓN ESTÁTICA


La configuración estática se logra de forma predeterminada al crear aplicaciones multicomponente. Si un diseño fija
las funciones de los componentes y las formas en las que los componentes se relacionan entre sí, se conectan entre
sí y realizan el procesamiento como parte de una aplicación más amplia, terminará con una configuración estática.
En tales situaciones, no hay necesidad de ningún servicio adicional para mapear dinámicamente los componentes
juntos; se considera que la única configuración se adapta a todas las situaciones. Si ejecuta la aplicación varias
veces, siempre obtendrá la misma asignación de componente a componente.
La identidad de los componentes de software se puede representar de varias formas diferentes. Los componentes
necesitan ID únicos que se puedan basar, por ejemplo, en su dirección IP o en una URL, siendo la URL más flexible porque
permite la reubicación de servicios sin dejar de identificar los componentes del servicio de forma única. Los ID de
componentes también pueden ser identificadores únicos de todo el sistema asignados por servicios como middleware,
específicamente con el propósito de mapear componentes juntos cuando es necesario pasar mensajes entre ellos.
La esencia de la configuración estática es que los componentes se conectan entre sí en función de asignaciones
decididas por el tiempo de diseño. Esto es más obvio si una referencia directa a la identidad de un componente se
incorpora a otro y se usa como base para formar conexiones o al menos enviar mensajes.
352 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Las aplicaciones configuradas estáticamente son generalmente más sencillas de desarrollar y probar que sus contrapartes
configuradas dinámicamente. Sin embargo, se basan en un conocimiento completo en tiempo de diseño de su comportamiento en
tiempo de ejecución y también del entorno en el que se ejecutan. Esto es muy difícil de confirmar a menos que la aplicación tenga un
alcance funcional muy limitado y comprenda una pequeña cantidad de componentes. Esto también significa que los sistemas
configurados estáticamente pueden necesitar actualizaciones de versión más frecuentes para hacer frente a cualquier cambio en el
entorno de tiempo de ejecución, porque cada configuración específica se fija para una configuración particular. Quizás, la limitación
más significativa de la configuración estática es que es inflexible con respecto a eventos dinámicos como fallas de componentes o
fallas de la plataforma específicamente dirigida donde se encuentra un recurso.

5.15.2 CONFIGURACIÓN DINÁMICA


La configuración dinámica de aplicaciones distribuidas aumenta la flexibilidad del tiempo de ejecución y potencialmente
mejora la eficiencia y la solidez. En el caso de la eficiencia, esto se debe a que los componentes se pueden mover entre
ubicaciones físicas para mapear mejor la disponibilidad de recursos, o las solicitudes de componentes se pueden desviar
dinámicamente a diferentes instancias de procesos del servidor (por ejemplo, para equilibrar la carga en un grupo de
procesadores). La solidez se mejora porque las asignaciones de componente a componente se pueden ajustar para tener en
cuenta eventos como la falla de un componente específico; así, por ejemplo, si un cliente está asignado a una instancia
particular de un servicio y esa instancia falla, entonces el cliente puede reasignarse a otra instancia del mismo servicio. Hay
mecanismos que se pueden utilizar para hacer esto automáticamente.
La esencia de la configuración dinámica es que los componentes se descubren entre sí en función de roles en lugar de
identificadores únicos de componentes. Es decir, los componentes saben qué tipos de servicios requieren y solicitan
conexiones a los componentes que brindan esos servicios sin conocer los ID de esos componentes de antemano. Por lo
general, se requieren servicios adicionales para facilitar esto, específicamente para anunciar los servicios proporcionados
por los componentes, o para encontrar servicios basados en una descripción de funciones, y para facilitar la conectividad
entre los dos procesos. Entre los ejemplos de servicios externos que facilitan el descubrimiento dinámico y la conectividad
se incluyen los servicios de nombres y el middleware.
Algunos servicios realizan una configuración dinámica internamente, por ejemplo, para
equilibrar la carga o para superar o enmascarar fallas de subcomponentes individuales del
servicio. Los mecanismos como los algoritmos de elección se utilizan a menudo para
seleccionar automáticamente un coordinador de un grupo dinámico de procesos cuya
membresía puede cambiar con el tiempo, a medida que diferentes nodos se unen y
abandonan el clúster de servicios. Un algoritmo de elección sigue varios pasos: en primer
lugar para detectar que un componente en particular ha fallado, en segundo lugar para
llevar a cabo una elección o negociación entre los componentes restantes para elegir un
nuevo coordinador, y finalmente para informar a todos los componentes de la identidad del
nuevo coordinador a suprimir elecciones adicionales innecesarias. Los algoritmos
electorales se analizan en detalle en el Capítulo 6.
Los mecanismos de configuración dinámica también facilitan el comportamiento sensible al contexto en los sistemas (consulte la siguiente

sección).

5.15.3 CONOCIMIENTO DEL CONTEXTO

La conciencia del contexto implica que el comportamiento o la configuración de una aplicación tiene en cuenta el contexto
operativo, es decir, ajusta dinámicamente su comportamiento o configuración para adaptarse al entorno o
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 353

condiciones de operación. Este es un aspecto complejo del comportamiento de los sistemas, que está fuera del alcance del libro en
general, pero que se presenta aquí muy brevemente para completarlo.
El contexto es información que permite a un sistema proporcionar una respuesta específica, en lugar de
genérica. Para dar un ejemplo muy simple, me preguntas el pronóstico del tiempo para mañana y yo respondo
"lloverá". Esto solo te sirve si previamente te hemos comunicado la ubicación a la que nos referimos (que
contextualiza tanto la pregunta como la respuesta en este caso). Un ejemplo relacionado con los servicios
distribuidos se refiere a la falla de una instancia de servidor. El número de servidores restantes es una información
de contexto muy importante porque si todavía hay cien servidores en funcionamiento, la falla de uno es
relativamente insignificante, pero si solo queda uno, o ninguno, entonces es grave y es necesario instalar nuevos
servidores. instanciado.
Los mecanismos de configuración dinámica y la información de contexto proporcionan una combinación poderosa para
permitir respuestas de reconfiguración sofisticadas y automatizadas a eventos como aumentos repentinos de carga o fallas
de componentes.

5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS


Hay una serie de requisitos no funcionales comunes de las aplicaciones distribuidas, la mayoría de los cuales
ya se han mencionado varias veces en varios contextos en el libro. Aquí, están relacionados y diferenciados.

Robustez. Este es un requisito fundamental de casi todas las aplicaciones distribuidas, aunque se puede
interpretar de diferentes formas. La solidez en el sentido de que no hay fallas a nivel de componente no es realista
porque no importa qué tan bien diseñado esté su software, siempre hay factores externos que pueden interrumpir
el funcionamiento de una aplicación distribuida. Los ejemplos incluyen un tráfico de red excesivo que causa
demoras o un tiempo de espera, una falla de la red que aísla un servidor de sus clientes y una falla de energía de la
computadora que aloja el servidor. Por lo tanto, un enfoque clave para la robustez es incorporar redundancia, es
decir, tener múltiples instancias de componentes críticos de manera que no haya un solo punto de falla (es decir, no
hay un solo componente que, si falla, causa que el sistema mismo fallar).
Disponibilidad. Este requisito se refiere a la proporción de tiempo que la aplicación o servicio está disponible para su
uso. Algunos servicios relacionados con negocios o finanzas pueden costarles a sus dueños grandes sumas de dinero por
cada hora que no estén disponibles; considere los sistemas de negociación de acciones, por ejemplo. Algunos sistemas,
como el monitoreo remoto de entornos peligrosos, como las centrales eléctricas y los sistemas de producción en fábrica,
son críticos para la seguridad y, por lo tanto, la disponibilidad debe estar lo más cerca posible del 100%. Puede encontrar el
término disponibilidad de “cinco nueves”, lo que significa que el objetivo es que el sistema esté disponible el 99,999% del
tiempo. La disponibilidad y la solidez a veces se confunden, pero técnicamente son diferentes; un ejemplo es el tiempo de
mantenimiento programado en el que un sistema no está disponible, pero no ha fallado. Otro ejemplo es cuando un
sistema puede admitir un cierto número de usuarios (digamos, 100). El usuario 101 se conecta al sistema y se le niega el
servicio, por lo que el servicio no está disponible para él específicamente, pero no ha fallado.

Consistencia. Este es el más importante de todos los requisitos no funcionales. Si los datos en el sistema no
permanecen consistentes, no se puede confiar en el sistema y, por lo tanto, ha fallado al más alto nivel. Para poner
esto en contexto con un ejemplo muy simple, considere una aplicación bancaria en la que los clientes pueden
transferir dinero entre varias de sus propias cuentas en línea (a través de Internet). Suponga que un cliente tiene £ 200
en su cuenta corriente y £ 300 en su cuenta de ahorros. Ella se mueve £ 100 del
354 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

cuenta corriente en la cuenta de ahorros. Esto requiere múltiples actualizaciones separadas dentro del sistema del
banco, posiblemente involucrando dos bases de datos diferentes y varios componentes de software. Supongamos
que el primer paso (eliminar £ 100 de la cuenta corriente) tiene éxito, pero el segundo paso (colocarlo en la cuenta de
ahorros) falla; el sistema se ha vuelto temporalmente inconsistente porque el crédito del cliente ha pasado de £ 500
hasta £ 400 cuando el total debería haber permanecido en £ 500. Si el sistema se ha diseñado bien, debe detectar
automáticamente que ha surgido esta inconsistencia y “revertir” el estado del sistema al estado consistente anterior
(en este caso, los valores de balance inicial).
Rendimiento (o capacidad de respuesta). Este es el requisito de que el sistema gestione una transacción dentro de un período
de tiempo determinado. Para las consultas dirigidas por el usuario, la respuesta debe ser oportuna en el contexto del uso de la
información. Por ejemplo, si la aplicación es la negociación de acciones, entonces una respuesta dentro de un segundo más o menos
tal vez sea aceptable, mientras que si se trata de un sistema de comercio electrónico en el que una empresa solicita lotes al por mayor
de productos de otra, una demora más prolongada de varios segundos. es adecuado ya que las transacciones no son tan críticas en el
tiempo. Consulte también la discusión sobre Programación para sistemas en tiempo real en el Capítulo 2.

El rendimiento constante también es importante para la confianza del usuario en el sistema. La variación en los tiempos de respuesta afecta

algunos aspectos de la usabilidad, ya que los retrasos prolongados pueden frustrar a los usuarios o provocar errores de entrada (p. Ej., Cuando

un usuario no está seguro de que el sistema ha detectado una pulsación de tecla y, por lo tanto, la vuelve a introducir, esto puede dar lugar a

pedidos duplicados, duplicados). pagos, etc.).

Escalabilidad. Este es el requisito de que debería ser posible aumentar la escala de un sistema sin cambiar el diseño. El
aumento podría deberse a la cantidad de usuarios simultáneos admitidos o al rendimiento (la cantidad de consultas o
transacciones manejadas por unidad de tiempo). La ampliación de un sistema para satisfacer la nueva demanda podría
implicar la adición de instancias adicionales de componentes (consulte Sección 5.16.1 ), colocando componentes críticos para
el rendimiento en plataformas de hardware más potentes o rediseñando componentes específicos de cuello de botella de
forma aislada, pero no debería requerir un rediseño de la arquitectura u operación general del sistema.

Es importante no confundir escalabilidad y capacidad de respuesta; la falta de escalabilidad a medida que aumenta la carga
puede ser la causa subyacente de una capacidad de respuesta reducida, pero son preocupaciones diferentes.
Extensibilidad. Debería ser posible extender la funcionalidad de un sistema sin necesidad de rediseñar el
sistema en sí y sin impacto en los otros requisitos no funcionales, la única excepción permisible es que puede haber
una compensación aceptable entre la adición de nuevas características y un correspondiente reducción de la
escalabilidad, ya que las nuevas funciones pueden conducir a un aumento de la intensidad de la comunicación.

Transparencia. Este es el requisito de que las complejidades internas de los sistemas se oculten a los usuarios
de manera que se les presente un sistema simple de usar, consistente y coherente. Esto se cita a menudo como la
métrica de calidad fundamental para los sistemas distribuidos.
Un objetivo de transparencia general es la abstracción de un solo sistema, de modo que a un usuario, o un proceso en
ejecución que necesita acceso a los recursos, se le presenta una interfaz bien diseñada para el sistema que oculta la
distribución en sí. Todos los recursos deben parecer disponibles localmente y se debe acceder a ellos con las mismas
acciones, independientemente de si son realmente locales o remotos. Como se mencionó en muchas otras secciones, hay
muchos tipos diferentes de transparencia y una amplia variedad de formas de facilitarla.
La provisión de transparencia se ve potencialmente afectada por el diseño de cada componente y la forma en
que interactúan. Debería ser un tema principal de preocupación durante la fase de análisis de requisitos porque
generalmente no es posible ajustar los mecanismos de transparencia a un diseño intrínsecamente no transparente.
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 355

Usabilidad. Esta es una etiqueta general para un amplio conjunto de preocupaciones que se superponen a varios de los otros
requisitos no funcionales, especialmente la capacidad de respuesta y la transparencia. La usabilidad también está relacionada con
algunos aspectos técnicos específicos, como la calidad de las interfaces de usuario y la coherencia en la forma en que se presenta la
información, especialmente si hay varias interfaces de usuario diferentes proporcionadas por diferentes componentes.
En general, cuanta más transparencia se proporciona, más utilizable es un sistema. Esto se debe a que los usuarios
están protegidos de tener que conocer detalles técnicos del sistema para poder utilizarlo. La usabilidad, a su vez, mejora la
corrección general porque con sistemas claros y fáciles de usar, en los que los usuarios no tienen que seguir procedimientos
complejos y no se les pide que tomen decisiones basadas en situaciones poco claras, hay menos errores cometidos por
usuarios o gerentes técnicos.

5.16.1 REPLICACIÓN
La replicación es una técnica de uso común en sistemas distribuidos, que no solo tiene el potencial de contribuir a
varios de los requisitos no funcionales identificados anteriormente, más notablemente robustez, disponibilidad y
capacidad de respuesta, sino que también tiene el potencial de interrumpir la coherencia si no se implementa
adecuadamente.
Esta sección se centra en las relaciones entre la replicación y los requisitos no funcionales de los sistemas
distribuidos. La transparencia y los aspectos mecánicos de la replicación se analizan con más detalle en el Capítulo
6.
La forma más sencilla de replicación es la replicación de la prestación de servicios en la que hay varias instancias de
servidor, pero cada una admite su propio conjunto de clientes, por lo que no se comparten datos entre los servidores. Este
enfoque se utiliza para mejorar la disponibilidad y la capacidad de respuesta, pero no mejora la solidez, ya que todavía hay
solo una copia del estado de cada sesión de cliente y solo una copia de los datos utilizados por cada cliente. No hay ningún
requisito para la propagación de la actualización de datos, sino que es necesario dirigir a los clientes a los servidores para
equilibrar la carga entre ellos, ya que si todos los clientes se conectan a un servidor, la replicación de la prestación del
servicio no tiene ningún efecto sobre el rendimiento. .
Considere el juego de casos de uso. Se pueden iniciar múltiples copias del servidor en diferentes
ubicaciones para lograr una forma simple de replicación sin la necesidad de modificar el diseño actual. Esto
replica la función, pero no los datos ni el estado. Cada cliente aún se conectaría a una instancia de servidor
específica (identificada por su dirección IP) y, por lo tanto, solo vería los otros jugadores conectados a la
misma instancia de servidor, anunciados en la lista de jugadores disponibles. Se podría admitir a más
usuarios en total, es decir, se mejora la disponibilidad y, dado que los usuarios pueden conectarse al servidor
geográficamente más cercano, la latencia de la red puede reducirse, lo que aumenta la capacidad de
respuesta. Sin embargo, los clientes están asociados, a través de su servidor, en grupos aislados. No hay
ningún mecanismo para mover juegos entre servidores o para hacer una copia de seguridad del estado del
juego en otros servidores;
Cuando se produce la replicación de datos, el alcance de los beneficios de rendimiento y el alcance del desafío para
administrar los datos y garantizar la coherencia de los datos están relacionados con el modo de acceso a los datos admitido,
específicamente si los datos pueden modificarse o son de solo lectura, durante las transacciones. Si la replicación está en
estado de aplicación activa o de recursos actualizables, la complejidad adicional puede ser muy alta debido a la necesidad de
propagar actualizaciones a todas las copias. Esto es relativamente más simple si la aplicación del usuario solo puede escribir
una copia de los datos compartidos, pero aun así, todavía existe un desafío significativo para garantizar que las copias que
se desconectan se actualicen correctamente cuando reaparecen. Hay tres escenarios comunes que ocurren:
356 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

1. Los datos son de solo lectura en todas las réplicas. Esto podría aplicarse a aplicaciones de suministro de información, como un
sistema de horarios de trenes en línea, en el que se podrían utilizar varios servidores para respaldar un
muchos clientes recuperan los detalles del viaje en tren de forma simultánea. Sin embargo, los datos en sí solo pueden
ser modificados por un sistema separado (un portal de gestión no disponible para los usuarios públicos). No hay
consultas de usuarios que puedan causar actualizaciones de datos. En los casos en que la replicación se realiza en varias
instancias de servidor de recursos de solo lectura, la complejidad adicional que surge de la replicación en sí es
relativamente baja y el esquema puede escalar muy bien.
2. La replicación se implementa de tal manera que solo se puede escribir una copia de los datos y las otras copias se pueden leer.
Los desafíos aquí son garantizar que solo una copia de los datos sea realmente escribible en un momento específico y también
garantizar que todas las actualizaciones de la copia escribible se copien de manera rápida y confiable en las otras copias. Esto
puede funcionar bien en aplicaciones en las que los accesos de lectura superan significativamente en número a los accesos de
escritura.
3. La replicación se implementa de manera que todas las copias de los datos se pueden escribir. Esto puede dar lugar a
varios problemas, incluido el problema específico de una actualización perdida, donde dos copias de un valor de datos
en particular se modifican en paralelo. Cuando cada uno de los cambios se propaga por todo el sistema, el que se
aplique en último lugar sobrescribirá el que se aplicó primero, es decir, se perdió la primera actualización. El problema
de la pérdida de actualización es importante porque ocurre incluso cuando todos los componentes funcionan
correctamente, es decir, no es causado por una falla, sino que es un artefacto del uso del sistema y el momento
específico de los eventos.
Este enfoque puede ser muy complejo de administrar y generalmente no es deseable porque, además del problema de
pérdida de actualización, existen varias formas en que el sistema puede volverse inconsistente.
El objetivo principal al agregar la replicación es garantizar que el sistema siga siendo coherente en todas las
circunstancias y escenarios de uso. Este debe ser siempre el caso, para garantizar la corrección de los sistemas, incluso
cuando la motivación y el propósito originales para implementar la replicación son mejorar la disponibilidad, la capacidad de
respuesta o la solidez. 3

Figura 5.39 ilustra una forma simple de replicación en la que una sola instancia del servicio (y por lo tanto los datos) está
disponible para los usuarios en un momento dado. Esto se debe a que todas las solicitudes de servicio se dirigen a la
instancia maestra del servicio, por lo que la instancia de respaldo es efectivamente invisible para los usuarios. Cuando una
solicitud de usuario hace que cambien los datos en poder del servidor, la instancia maestra actualiza su copia local de los
datos y también propaga cualquier actualización a la instancia de respaldo. La instancia de respaldo monitorea la presencia
de la instancia maestra. Esto podría, por ejemplo, ser facilitado por la instancia maestra enviando un mensaje de estado a la
instancia de respaldo periódicamente, en cuyo caso si estos mensajes cesan, la instancia de respaldo se da cuenta de que la
instancia maestra ha fallado. Figura 5.39 muestra la situación cuando ambas instancias del servicio están en buen estado y
se realizan actualizaciones en ambas réplicas de los datos. La mecánica del paso 1 (partes ayb) en Figura 5.39 podría basarse
en multidifusión o difusión dirigida o mediante el uso de un mecanismo de comunicación de grupo, que se analiza en el
Capítulo 6.

3 Los mecanismos de replicación brindan un muy buen ejemplo de la regla general de que cada vez que se agrega

una nueva característica a una aplicación o sistema, por cualquier motivo, potencialmente presenta desafíos
adicionales o nuevos modos de falla. Eludir los nuevos desafíos o protegerse contra estos nuevos modos de falla
puede ser costoso en términos de esfuerzo de diseño y desarrollo y especialmente de pruebas (que deben cubrir un
amplio espacio de estados de posibles escenarios). En última instancia, podemos encontrarnos haciendo lo que el
autor denomina "persecución de la cola de la complejidad", en el que añadimos capas cada vez mayores de
complejidad para abordar los problemas que surgen de la complejidad de las capas anteriores. Por lo tanto, antes
de agregar cualquier mecanismo adicional como la replicación,
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 357

2. El servidor maestro Servidor


responde, el cliente Maestría
Datos
establece una aplicación ejemplo
sesión, lo que lleva a

actualizaciones de datos en el servidor

3. Instancias de servidor
comunicarse con Servidor de respaldo

propagar datos ejemplo


1b. Mensaje del cliente
cambios desde el mantiene réplica
Cliente se propaga copia de datos maestros a la copia de datos
1a. El cliente envía una en todo el servicio
copia de datos de respaldo
solicitud al servicio.

Servidor
Clave
Respaldo
Comunicación del cliente del servicio de archivos con el servicio de archivos Datos
Detalles visibles para el cliente
ejemplo
Detalles ocultos para el cliente

Comunicación interna del servicio entre componentes Límite lógico del servicio.
El cliente ve una única entidad de servicio y
no conoce la cantidad de servidores o
Límite de servicio la configuración interna del servicio

FIGURA 5.39

Replicación de datos de respaldo maestro del estado y los datos de la aplicación activa.

Figura 5.40 ilustra la adaptación de la configuración del servicio replicado que se produce cuando falla la instancia del
servidor maestro. Inicialmente, habrá un período en el que el servicio no estará disponible, porque la instancia de respaldo
aún no ha detectado la falla del maestro anterior, por lo que no ha asumido el rol de maestro. Una vez que la instancia del
servidor de respaldo detecta que el maestro ha fallado, asume el control como maestro (esto también se describe como
promovido al estado maestro). A partir de este momento, esta instancia de servidor se ocupa de las solicitudes de servicio.

Clave

Comunicación del cliente del servicio de archivos con el servicio de archivos


Servidor
Detalles visibles para el cliente
Maestría
Detalles ocultos para el cliente Datos
ejemplo
Límite de servicio

1a. Servidor de respaldo


2b. El mensaje del cliente
2a. El cliente envía un detecta falta de
se propaga a través de
solicitud al servicio Servidor maestro.
el servicio. Detectado
Cliente
por el nuevo maestro 1b. Servidor de respaldo
servidor asume el papel de maestro

3. El servidor maestro (recién Nuevo

ascendido) responde, el Maestro


Datos
el cliente establece un servidor
sesión de aplicación

Límite lógico del servicio

FIGURA 5.40

Escenario de promoción de copia de seguridad en la replicación de datos de copia de seguridad maestra.


358 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

El mecanismo por el cual se detecta la falla de la instancia maestra debe ser confiable en sí mismo. La detección
generalmente se basa en algún tipo de mecanismo de latido, de modo que el servidor maestro en buen estado envía un
mensaje periódico para informar a la copia de seguridad que aún está en buen estado. Esto puede omitirse cuando se
realizan actualizaciones con regularidad (porque los mensajes de actualización también sirven para informar a la copia de
seguridad que el maestro aún está en buen estado, sin agregar ninguna comunicación adicional) y solo se enciende si el
intervalo entre actualizaciones excede algún umbral. Por lo tanto, la copia de seguridad no debe esperar más de un período
especificado sin un mensaje del maestro. Sin embargo, la propia red puede perder o retrasar los mensajes y, por lo tanto,
no es seguro activar el cambio de copia de seguridad si se omite un solo mensaje de latido; quizás, tres mensajes omitidos
en secuencia son apropiados en algunos sistemas. La configuración del esquema de latidos (que incluye el intervalo entre
mensajes y la cantidad de mensajes que se deben perder en secuencia para que sirva como confirmación de que el maestro
ha fallado) debe ajustarse para la aplicación específica, ya que representa un intercambio de tres vías. entre la capacidad de
respuesta del sistema de copia de seguridad, los gastos generales del mensaje para mantener el sistema de copia de
seguridad y también el riesgo de una falsa alarma, que introduce un riesgo adicional de inconsistencia de datos si ambas
copias se pueden escribir simultáneamente.

5.16.2 SEMÁNTICA DE REPLICACIÓN


Al implementar mecanismos como la replicación, es importante considerar cuidadosamente los méritos de las
diversas formas alternativas de lograr la funcionalidad requerida. Para la replicación, la semántica se ocupa de la
forma real en que se comportan los mecanismos de replicación en términos de la forma en que manipulan los datos
del sistema. Los problemas que deben tenerse en cuenta incluyen los siguientes:

• ¿Qué debería suceder cuando la copia maestra deja de estar disponible, si la copia de respaldo debe estar
disponible para el acceso o se mantiene solo para establecer la consistencia del sistema una vez que se ha
reparado el servidor maestro?

• Si la copia de respaldo está disponible (en caso de falla del maestro), existe el problema de si debe ser de solo lectura
o de lectura y escritura; la principal preocupación es que las dos copias podrían desincronizarse. Esto podría suceder
si se producen actualizaciones en la copia de seguridad y luego también falla; cuando la copia maestra anterior
vuelve a estar en línea, no tiene conocimiento de las transacciones intermedias. ¿Los roles de maestro y de respaldo
• están preasignados o surgen dinámicamente del comportamiento del sistema (por ejemplo, la instancia a la que se
accede más se puede asignar automáticamente para que sea la instancia maestra)? Si los roles se asignaron
previamente, ¿qué debería suceder después de que un maestro que había fallado (y por lo tanto, la instancia de
respaldo inicial ahora actúa como maestro) se recupera? ¿El maestro original recupera su función de maestro o
asume el estado de copia de seguridad?
• Algunas implementaciones de replicación emplean un número impar de instancias de servidor (al menos tres)
de modo que, en el caso de que las copias no estén sincronizadas, se puede realizar una votación, es decir, se
toma el valor correcto como el valor mayoritario. Sin embargo, no hay garantías absolutas de que la mayoría
sea correcta (es menos probable, pero posible, que dos de los tres hayan perdido una actualización en
particular). Tampoco hay garantía de que haya un subconjunto mayoritario (considere un grupo de cinco
instancias de servidor, en las que una ha fallado y las cuatro restantes se dividen con dos con un valor de datos
particular y las otras dos con un valor diferente).

Figura 5.40 ilustra uno de los posibles escenarios de respaldo cuando falla la copia maestra. En el enfoque ilustrado,
tras la detección de una falla maestra, la instancia de respaldo se promueve a sí misma como maestra
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 359

estado (es decir, asume el papel de maestro). La coherencia de los datos se conserva siempre que la instancia maestra
anterior haya propagado todas las actualizaciones de datos a la (entonces) copia de seguridad, lo que debería hacer si
funciona correctamente.

5.16.3 UNA IMPLEMENTACIÓN DE REPLICACIÓN


Se proporciona una aplicación de demostración para ilustrar la implementación y el funcionamiento de la replicación en el
contexto de una aplicación de base de datos simple. El mismo tema de base de datos que se utiliza en Actividad A1 continúa,
pero en este caso, hay una sola base de datos que se replica, en lugar de dos bases de datos diferentes, como se usó en la
actividad anterior. En este ejemplo específico, la replicación se ha utilizado para garantizar que el servicio sea sólido frente a
fallas en el proceso del servidor. Una única instancia de estado maestro del servicio se ocupa de las solicitudes de servicio
del cliente. La instancia maestra también transmite mensajes de latidos periódicos para señalar su presencia a otras
instancias del servicio. Puede existir una instancia adicional que tenga el estado de copia de seguridad; su función es
supervisar el estado de la instancia maestra mediante la recepción de mensajes de latido. Si se detecta la ausencia de tres
mensajes de latido sucesivos, la instancia de respaldo se promueve a sí misma al estado maestro. La instancia maestra del
servicio propaga las actualizaciones de datos realizadas por el cliente a la instancia de respaldo, por lo tanto, mantener los
datos almacenados en la instancia de respaldo sincronizados con la instancia maestra y, por lo tanto, mantener la
coherencia del servicio. Si la copia de seguridad tiene que tomar el control de la instancia maestra, los datos estarán
actualizados y reflejarán los cambios realizados antes de que la instancia maestra fallara.
Para mostrar la variedad de opciones de diseño disponibles, la implementación utiliza un medio
alternativo para que los clientes ubiquen el servicio al que se muestra en Figuras 5.39 y 5.40 . La
técnica que se muestra en esos ejemplos se basa en que el cliente envía un mensaje de difusión de
descubrimiento de servicio y la instancia maestra del servicio responde. En cambio, la implementación
del servicio replicado de demostración utiliza publicidad de servicio en la que la instancia maestra del
servicio envía mensajes de difusión a intervalos cortos regulares de unos pocos segundos. Un cliente
recién iniciado debe esperar para recibir un mensaje de anuncio de servicio que contiene la dirección
IP y los detalles del puerto necesarios para conectarse al servicio. Si la instancia del servidor de
respaldo se eleva al estado principal, se encarga de enviar las difusiones de anuncios del servicio, de
modo que los clientes siempre detectan la instancia principal actual del servicio. En esta
implementación,
Figura 5.41 muestra el comportamiento interno del servicio que determina el estado de cada instancia de la aplicación de base de
datos replicada. El diagrama muestra el comportamiento de un solo proceso; cada proceso mantiene su propia copia de la lógica de
transición de estado y representa su estado internamente como un par de variables. En este caso, las variables de estado que
gobiernan el comportamiento de la transición de estado son las siguientes:

m_ServerState {Backup, Master} Un tipo enumerado


m_iHeartbeatMissedCount ≥ 0 Un entero

Cada vez que se detecta un latido dentro del período de tiempo esperado, la variable m_iHeartbeatMissedCount se
restablece a 0. Cuando se agota el tiempo de espera (el latido no se detectó en el período de tiempo esperado), la
variable se incrementa. Si la variable alcanza el valor 3, la instancia de respaldo se eleva al estado maestro. Hay dos
formas en las que una instancia de estado maestro puede dejar de existir; en primer lugar, si falla o se elimina
intencionalmente del sistema y, en segundo lugar, si detecta algún mensaje de latido de otra instancia maestra (en
cuyo caso se degrada al estado de respaldo). Este es un mecanismo a prueba de fallas para evitar la coexistencia de
múltiples instancias maestras.
360 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

Tiempo de espera, menos de tres


latidos cardíacos consecutivos perdidos
m_iHeartbeatMissedCount ++
Tiempo de espera, tres consecutivos
latidos del corazón perdidos

Inicialización Clave
m_iHeartbeatMissedCount = 0
Estado inicial

Respaldo Maestría
Expresar

Transición

Latido detectado Latido de otro maestro detectado


m_iHeartbeatMissedCount = 0 m_iHeartbeatMissedCount = 0

FIGURA 5.41

El diagrama de transición de estado de la aplicación de demostración de la base de datos replicada.

Hay dos tipos de comunicación dentro de la aplicación de demostración de replicación: comunicación


dentro del propio servicio (entre las instancias del servidor) y comunicación entre el cliente de la aplicación y
la instancia maestra del servicio. Figura 5.42 muestra la conectividad a nivel de socket entre los distintos
componentes.
Figura 5.42 muestra la comunicación a nivel de socket dentro de la aplicación de demostración de
replicación. La comunicación entre el cliente de la aplicación y la instancia maestra del servicio se
muestra a la izquierda. Comprende que el servidor envía anuncios de servicio, que se transmiten a
través de UDP y que el cliente utiliza para obtener los detalles de la dirección del servidor y, por lo
tanto, conectarse mediante TCP. La conexión TCP se utiliza para todas las solicitudes y respuestas de
la aplicación entre el cliente y el servidor. La comunicación entre la instancia maestra del servicio y la
instancia de respaldo se muestra a la derecha. Ambos procesos tienen los mismos sockets, pero los
sockets de difusión y los sockets TCP utilizados para conectarse a los clientes están inactivos en
cualquier instancia que esté en estado de respaldo. Solo la instancia maestra transmite mensajes de
latido, que recibe la instancia de respaldo.
El comportamiento de la aplicación de demostración de replicación se explora en Actividad A3 . El lleno
El código fuente está disponible como parte de los recursos que acompañan al libro.

Anuncio del servidor


difusión (UDP)
Latido del corazón

S SA_Bcast transmisión S SA_Bcast


(UDP)
S SA_Recv S HB_Bcast S HB_Bcast
S Escuchar S Escuchar

Aceptar crea S HB_Recv S HB_Recv


Actualizar
Solicitud zócalo de aplicación Instancia del servidor Propagación Instancia del servidor

Cliente (estado = maestro) transmisión (estado = respaldo)


S Aplicación S Aplicación
S UP_Bcast (UDP) S UP_Bcast S Aplicación

Mensajes de aplicación
(solicitudes de datos y actualizaciones)
a través de una conexión TCP
S UP_Recv S UP_Recv

Clave

proceso enchufe

FIGURA 5.42

La conectividad a nivel de socket entre los componentes del servicio de replicación.


5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 361

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO

Se utiliza una aplicación de base de datos replicada para investigar el comportamiento de un mecanismo de replicación de datos, así como aspectos de
la configuración dinámica del servicio y la asignación de roles de componentes mediante el uso de mensajes de latido, propagación de actualización
de datos entre instancias de servidor y difusiones de anuncios de servicio para permitir a los clientes localizar la instancia del servicio maestro.

Esta actividad utiliza los programas Replication_Client y Replication_Server. Para simplificar la configuración del software y asegurar que el foco de
la experimentación esté en los aspectos arquitectónicos de la replicación, los servidores de bases de datos realmente mantienen sus datos en forma
de tablas de datos en memoria. Inicialmente, los valores están codificados de forma rígida, pero se pueden actualizar a través de las solicitudes de los
clientes. Cualquier actualización que ocurra en la instancia del servidor maestro se propaga a la instancia del servidor de respaldo.

Durante los experimentos, observe la información del evento de diagnóstico que se muestra en cada componente, que proporciona
detalles del comportamiento interno.

Prerrequisitos
Se necesitan dos computadoras en red porque cada instancia del servicio debe vincularse al mismo conjunto de puertos; por lo tanto, no
pueden ser coresidentes en la misma computadora. Dado que se utiliza la comunicación por difusión, las computadoras deben estar en
la misma red local.

Los resultados del aprendizaje


• Comprender el concepto de replicación de datos.
• Familiarizarse con un mecanismo de replicación específico
• Para explorar el comportamiento de una aplicación de base de datos replicada simple

• Para explorar la configuración automática del servicio y la asignación de roles de componentes

• Para explorar el descubrimiento dinámico de servicios con difusiones de anuncios de servicios Para

• explorar la propagación de actualizaciones

• Obtener una apreciación de la transparencia de fallas en un entorno de aplicación práctica


La actividad se realiza en cinco etapas.

Método Parte A: Autoconfiguración y autoadministración de componentes (un servidor)


Esta parte de la actividad tiene que ver con la autoconfiguración que se produce cuando se inicia una única instancia de servidor
del servicio de base de datos replicada.
Inicie una única copia del programa cliente Replication_Client y el programa servidor Replication_Server en diferentes equipos. El proceso del
servidor se inicializa a sí mismo al estado de copia de seguridad. Escucha los mensajes de latidos del corazón, y porque lo hace
no detecta ninguno (cuenta tres latidos perdidos consecutivamente), se eleva al estado maestro. Una vez en estado maestro, comienza a
transmitir anuncios de servicio periódicos. Esto es para permitir que cualquier cliente localice el servidor.
Inicialmente, el proceso del cliente no conoce la dirección del servidor, por lo que no puede enviar una solicitud de conexión.
Observe cómo recibe un mensaje de anuncio de servicio (que contiene los detalles de la dirección del servidor), actualiza su registro de
la dirección del servidor y luego usa esta información para conectarse automáticamente al servicio.

Resultado esperado para la Parte A


Debería ver que el servidor se inicializa a sí mismo al estado de copia de seguridad, luego espera los mensajes de latido y no
recibe ninguno, y se eleva al estado maestro. En este punto, verá que comienza a enviar anuncios de servicio y mensajes de
latido.
El proceso del cliente recibe el anuncio del servidor.
La siguiente captura de pantalla muestra la instancia del servidor inicializándose al estado de respaldo y luego elevándose al estado
maestro, momento en el cual comienza a enviar mensajes de latido y mensajes de publicidad del servidor.
362 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

Las siguientes capturas de pantalla muestran el componente del cliente esperando el mensaje de anuncio del servicio y luego
recibiéndolo y actualizando los detalles de la dirección del servidor que contiene.
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 363

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

Método Parte B: Uso del servicio de base de datos


Ahora se puede utilizar la aplicación. Experimente conectando el cliente al servidor y solicitando elementos de datos del servidor. Los valores de datos
almacenados en el servidor también se pueden actualizar; pruebe algunas solicitudes y algunas actualizaciones.

Resultado esperado para la Parte B


El cliente debe conectarse al servidor (establece una conexión TCP). Debería poder realizar solicitudes de datos y
actualizaciones en el cliente y ver el efecto de estas en el servidor.
La siguiente captura de pantalla muestra el estado del servidor después de que el cliente se ha conectado y el cliente ha cambiado
el nombre del número 101 de cliente de "Fred" a "Frederick".
364 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

La captura de pantalla a continuación muestra el estado correspondiente de la interfaz del cliente después de que el valor de los datos se actualizó y se envió al

servidor.

Método Parte C: Autoconfiguración de componentes (dos servidores)


Esta etapa explora la autoconfiguración que ocurre cuando hay dos instancias de servidor presentes.
Inicie dos instancias del servicio en diferentes equipos. Un proceso debe promoverse a sí mismo al estado de maestro (la misma
secuencia de eventos que se exploró en la parte A); la segunda instancia luego detecta los mensajes de latido del proceso maestro, lo
que hace que permanezca en el estado de respaldo.

Resultado esperado para la Parte C


Debería ver que, al usar el mecanismo de latido, el servicio se autoconfigura para que haya una instancia
maestra y una instancia de respaldo.
Esta captura de pantalla muestra la instancia de servicio que se eleva a maestra. Por lo general, es el que se inicia primero, porque
cada instancia espera el mismo período de tiempo para detectar mensajes de latido, y el primero en comenzar a esperar es el primero en
llegar al final del período de espera y elevar.
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 365

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

Esta captura de pantalla (a continuación) muestra la instancia del servidor que permanece en estado de respaldo porque recibe los mensajes de
latido de la instancia maestra.
366 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

Método Parte D: Actualización de la propagación en funcionamiento


Inicie dos instancias del servicio en diferentes computadoras (o continúe desde la parte C).
Inicie un cliente en la misma computadora que una de las instancias del servidor o use una tercera computadora. El cliente recibirá mensajes
de anuncios de servicio de la instancia maestra y, por lo tanto, siempre se conectará a la maestra; confirmar esto experimentalmente.

Observe que el cliente con ID 102 inicialmente tiene el nombre "Jane". Use el cliente para cambiar esto a "John" (solicite los datos,
luego edite manualmente los datos en la interfaz de usuario del cliente y luego use el botón "Enviar datos actualizados" para enviar el
nuevo valor a la instancia del servidor maestro).

Resultado esperado para la Parte D


Debería ver que el cliente realiza correctamente la actualización, utilizando la secuencia de solicitud-cambio-envío descrita anteriormente.
La interfaz del cliente se muestra en la siguiente captura de pantalla.

La instancia del servidor maestro recibe el mensaje de solicitud de actualización del cliente, realiza la actualización en su propia copia de los datos y también

propaga la actualización a la instancia del servidor de respaldo (como se muestra en la captura de pantalla a continuación) para mantener la consistencia de los

datos.
5.16 REQUISITOS NO FUNCIONALES DE LAS APLICACIONES DISTRIBUIDAS 367

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

La instancia del servidor de respaldo recibe la actualización propagada de la instancia maestra y actualiza su copia de los datos en consecuencia;
Vea la captura de pantalla a continuación.
368 CAPÍTULO 5 LA VISTA DE ARQUITECTURA

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

Método Parte E: Reconfiguración automática y transparencia de fallas


Esta etapa explora el comportamiento cuando falla la instancia maestra y el servidor de respaldo detecta la falta de mensajes de
latido.
Inicie una instancia del servicio en cada uno de dos equipos diferentes. Observe mientras el servicio se autoorganiza (es decir, uno de los
servidores se convierte en la instancia maestra y el otro permanece en estado de respaldo).
Ahora, cierre la instancia maestra (simulando un bloqueo). Observe el comportamiento de la instancia de respaldo. Debería detectar
que el maestro ya no está presente (no hay mensajes de latido) y, por lo tanto, ascender al estado de maestro.
Una vez que el nuevo maestro se haya establecido, reinicie el otro servidor (que originalmente era el maestro). Al iniciarse, debe
detectar los mensajes de latido que envía la instancia maestra actual y, por lo tanto, el servidor reiniciado debe permanecer en el estado de
respaldo.

Resultado esperado para la Parte E


La siguiente captura de pantalla muestra la instancia del servicio de respaldo que detecta la ausencia del maestro: cuando se pierden
tres latidos consecutivos, se promueve a sí mismo al estado de maestro y comienza a transmitir mensajes de latidos y anuncios del
servidor.

Cuando se reinicia la otra instancia del servicio (que anteriormente era la maestra y luego se bloqueó), detecta
los mensajes de latido del maestro actual y, por lo tanto, asume el estado de respaldo, como se muestra en la captura de pantalla a continuación. Tenga
en cuenta el nuevo ID de servidor de la instancia reiniciada (1884), en lugar de su ID original (1319) cuando se estaba ejecutando anteriormente
(evidenciado en la captura de pantalla anterior cuando estaba enviando mensajes de latido). Esto se debe a que el ID se genera aleatoriamente cuando
se inicia el proceso del servidor. Tenga en cuenta también que el ID de la otra instancia (ahora maestra) permanece sin cambios (1355).
5.17 APLICACIONES Y REDES DISTRIBUIDAS 369

ACTIVIDAD A3 EXPLORANDO EL MECANISMO DE REPLICACIÓN DE DATOS DE RESPALDO MAESTRO — Cont.

Reflexión
Esta actividad facilita la exploración de la replicación de datos en un entorno de aplicación realista. A través de la experimentación práctica, puede ver
cómo operan varios mecanismos importantes (publicidad de servicios, mensajes de latidos y propagación de actualizaciones de datos). Estos se utilizan
para lograr el descubrimiento automático de componentes y la autoconfiguración del servicio, así como el logro de un nivel superior de replicación
activa de datos para lograr un servicio de base de datos sólido y transparente a fallas.
Se recomienda que experimente más con la aplicación de demostración de replicación para obtener una comprensión profunda
de sus diversos comportamientos. También debe inspeccionar el código fuente e intentar unir el comportamiento observado con la
lógica del programa subyacente.

5.17 LA RELACIÓN ENTRE APLICACIONES DISTRIBUIDAS Y


REDES
Los sistemas distribuidos agregan administración, estructura y, lo que es más importante, transparencia además de
la funcionalidad proporcionada por las redes subyacentes para lograr su conectividad y comunicación. Por lo tanto,
las aplicaciones distribuidas deben considerarse en una capa conceptualmente por encima de la parte superior de
la pila de protocolos de red y no como parte de la capa de aplicación.
Para poner esto en contexto, considere el Protocolo de transferencia de archivos (FTP). Este protocolo de capa de aplicación de
uso común se puede realizar en un formulario de solicitud, es decir, una utilidad de transferencia de archivos, y también se puede
incrustar en aplicaciones que pueden integrar una función de transferencia de archivos dentro de su operación general (como la
configuración del sistema y las utilidades de administración y instaladores de software automatizados). Ver Figura 5.43 .

También podría gustarte