sábado, 5 de abril de 2008

Dominios de aplicaciòn en .NET (App Domains)

Todos sabemos que .NET ejecuta còdigo administrado a travès de Dominios de aplicaciòn, pero conceptualmente no son muchos los desarrolladores .Net que comprenden en profundidad esta arquitectura y sus implicancias.
Por este motivo he decidido compilar un capìtulo interesante del libro "Programming .Net Components 2nd. Ed." que trata sobre este tema.

Còdigo administrado en .NET y dominios de aplicación

Todas las aplicaciones y componentes .NET requieren de un ambiente administrado para ejecutarse. Para esto .NET utiliza un “Dominio de Aplicación” (Application Domain), que permite la ejecución de còdigo administrado de parte de los “Ensamblados” (Assemblies).
El “Dominio de Aplicación” serìa el equivalente en .NET al concepto de Proceso del S.O., con una gran diferencia: dentro de un proceso fìsico del S.O. pueden hostearse mùltiples de estos “Application Domains” . Podrìamos entonces considerarlos como “procesos lògicos” dentro de un proceso real del S.O.
( figura 1)
Esta arquitectura de “Application Domains” posee grandes ventajas con respecto a la tradicional de poseer cada aplicación(exe) y c/u de sus componentes(dlls) dentro de su propio y exclusivo proceso. Los procesos tradicionales son denominados en .NET como “còdigo no administrado”.

Algunas desventajas de esta arq. de multiples procesos son:

  • Crear y Destruir un proceso del S.O. consume mucho tiempo.

  • Mantener un proceso en ejecución es costoso en tèrminos de memoria y de los recursos que el S.O. debe ubicar en ellos.
  • Realizar llamadas entre procesos resulta en penalidades de tiempo, ya que cruzar los lìmites de un proceso es mucho màs costoso que realizar un llamado directo dentro del mismo. Esto es porque se necesitan mecanismos especiales para efectuar los llamados inter-proceso (por ej.: pipes, sockets, LPC/RPC) .

  • El còdigo en los procesos clientes se vuelve complejo para realizar llamados a otros procesos y obviamente difiere de los llamados internos.
Ventajas de los “Application Domains”:

  • Baja sobrecarga en el S.O. por permitir que mùltiples “procesos lògicos” se hosteen en el mismo proceso real que administra el S.O.
  • Los tiempos que requiere Crear o destruir un “App.Domain”, y mantenerlo en ejecución con sus recursos asignados, es una fracciòn del requerido por un proceso fìsico.
  • Los llamados entre “App. Domains” que estàn dentro del proceso fìsico son mucho màs ràpidos que los llamados entre diferentes procesos del S.O.
  • .NET mantiene un lìmite de seguridad estricto entre “App.Domains”, por lo cual los objs. del “App.Domain A” no pueden interferir con los objetos del “App.Domain B”; a menos que estos objs. decidan cooperar usando .Net Remoting.

Es importante destacar que para mantener las 2 grandes ventajas de la arq. tradicional de “mùltiples procesos”: “Aislamiento ante fallas” y “Seguridad”, cada “App.Domain” carga y mantiene su propio juego de Assemblies. En la figura 1 , la librerìa de clases llamada “Assembly 1” se carga 2 veces, una en cada App.Domain (B y C), los cuales poseen su propia copia independiente.

La plataforma .NET y los “App. Domains”
El RunTime de .Net es un juego de Windows DLLs, implementadas en còdigo no administrado con C++; estas proveen : administración del Heap, recolector de basura (GC), compilador JIT (JustInTime), Cargador y adm. de assemblies, y otras herramientas que hacen posible el “còdigo administrado”.
El “App.Domain” habilita a los Assemblies que carga, a acceder a estos servicios del RunTime .Net. Por este motivo se dice que los App.Domains son el puente que une el Mundo de còd. administrado con el Mundo de còd. no administrado.
( figura 2)
Es importante notar en la figura 2 que todos los App.Domain del mismo proceso comparten el mismo “administrador de Heap”.

Threads (Hilos) y App.Domains

Los Threads en .Net no son afines a los App.Domains, esto implica que un thread puede entrar y salir en cualquier Dominio que se ejecute en el mismo proceso subyacente. Por lo tanto nada previene que un Thread creado en un App Domain acceda a los objs. de otro App Domain en el mismo proceso.

App Domains y Remoting

.Net usa la misma arq. de llamados Remotos entre App Domains para:
· 2 App Domains en el mismo proceso
· 2 App Domains en 2 procesos distintos del S.O.
· 2 App Domains en 2 màquinas fìsicas distintas.

(figura 3)

Los clientes que estàn en el mismo App.Domain del obj. llamado pueden tener una referencia directa al obj. En cambio los clientes que estàn en diferentes App.Domains usan un Proxy para conectarse al objeto.
Un Proxy es un obj. que provee exactamente las mismas interfaces, mètodos pùblicos, propiedades y miembros que el obj. real, aunque el Proxy no puede servir al cliente debido a que el còdigo del objeto llamado y su estado residen donde el obj. estè.
Todos los proxys saben como ligarse al obj. y enviarle los llamados hechos por el cliente, esta operación es denominada “marshaling”.
El marshaling cumple con el objetivo de darle al cliente la ilusiòn de que està llamando a un objeto local y darle al servidor la ilusiòn de que està sirviendo a un cliente local. Ni cliente, ni servidor usan mecanismos remotos (pipes, RPC, sockets), debido a que estos detalles estàn encapsulados en el Proxy.
.Net requiere que si un obj. es accedido por un Proxy, la clase del obj. debe derivar de la clase abstracta “MarshallByRefObject”.

3 comentarios:

Anónimo dijo...
Este comentario ha sido eliminado por un administrador del blog.
John Ortiz Ordoñez dijo...

Gracias por compartir el conocimiento que tienes de los App Domains. He empezado a escribir sobre este tema en mi blog, además de reflection y metadatos; y lo que acabo de leer en este artículo me ha servido para asentar bases sobre el primer tema, sobretodo.

Saludos desde Bogotá D.C.

Unknown dijo...

Hola Jorge:

Muchas gracias por esta útil información que me ayuda a comprender mejor como funcionan las aplicaciones en .NET.

Ojalá también escribieras sobre el comportamiento de los threads entre distintos appdomain, ya que esto ayudaría a comprender mejor temas como el diseño de un Singleton que sea, por ejemplo, thread-safe.

Saludos.

Xabier.