800 likes | 923 Views
XML, Distribución y Componentes Tema 6 – Aplicaciones Distribuidas: .NET Remoting http://paginaspersonales.deusto.es/dipina/MasterISW/. Dr. Diego Lz. de Ipiña Gz. de Artaza http://paginaspersonales.deusto.es/dipina (Personal) http://www.morelab.deusto.es (Research Group)
E N D
XML, Distribución y ComponentesTema 6 – Aplicaciones Distribuidas: .NET Remotinghttp://paginaspersonales.deusto.es/dipina/MasterISW/ Dr. Diego Lz. de Ipiña Gz. de Artaza http://paginaspersonales.deusto.es/dipina (Personal) http://www.morelab.deusto.es (Research Group) http://www.smartlab.deusto.es (Research Lab) http://www.ctme.deusto.es (Cátedra de Telefónica Móviles) http://www.tecnologico.deusto.es (Tecnológico-Fundación Deusto)
Temario • Procesamiento XML en .NET (21 y 22 Febrero) • Estándar .NET [XML.NET] • Soporte XML [XML-SAX, XML-DOM, Validación] • XSL [XPath, XSLT, Scripts, Objetos de extensión] • Aplicaciones distribuidas (23 Febrero, 5 Marzo) • XML/SOAP • .NET Remoting • Mensajería • Componentes .NET (6 y 7 Marzo) • Metadatos y Reflexion • Componentes .NET y Enterprise Services • Complementos • Interoperabilidad COM y P/Invoke • COM+ y MTS • MSMQ (colas de mensajes)
Contenidos Parte Aplicaciones Distribuidas • WebServices y SOAP • .NET Remoting • Mensajería
Introducción • ASP.NET es la herramienta adecuada para la construcción de clientes ligeros que sólo visualizan lenguaje de marcado a través de un navegador • Hay aplicaciones que se benefician de una mayor acoplamiento entre el cliente y el servidor • Se comportan mejor en la comunicación a dos bandas entre el cliente y el servidor • Utilizan la red de manera más óptima • Facilitan el mantenimiento del estado de sesiones • El espacio de nombres System.Runtime.Remoting provee la infraestructura para el desarrollo de este tipo de aplicaciones al estilo de DCOM
.NET Remoting • Remoting sustituye a la tecnología DCOM para crear aplicaciones distribuidas sobre plataformas Windows. • Remoting proporciona una arquitectura orientada a objetos, que permite desarrollar de forma sencilla aplicaciones distribuidas.
Características • NET Remoting permite construir aplicaciones distribuidas. • Todos los componentes de aplicación pueden concentrarse en un único ordenador o en múltiples servidores alrededor de Internet. • .NET Remoting permite a las aplicaciones cliente utilizar objetos ubicados en cualquier ordenador conectado a la Red. • Podemos decir que Remoting permite invocar métodos y pasar objetos más allá de los dominios de nuestra aplicación.
Características • La arquitectura .NET remoting es flexible, permitiendo una fácil personalización de la aplicación. • En vez de utilizar mecanismos propietarios Remoting soporta estándares ya existentes como: • SOAP (Simple Object Access Protocol) • HTTP y TCP como protocolo de comunicación. • Proporciona servicios y canales de comunicación que transmiten mensajes entre aplicaciones remotas. • Proporciona formateadores que codifican y decodifican los mensajes que se transmiten por los canales.
Conceptos Básicos • Un clase es remota cuando puede ser usada por clientes en otro dominio de aplicación: en el mismo proceso, en otro proceso o en otras máquinas • Para construir una clase remota en primer lugar hay que hacer que la clase derive de: System.MarshalByRefObject public class RemotableClass: MarshallByRefObject { ... }
Conceptos Básicos Client application domain Server application domain Client Marshall-by- reference object Proxy Channel
Conceptos Básicos • Cuando un cliente crea una instancia de RemoteClass, realmente se crea un proxy de la misma • Llamadas recibidas por el proxy son transmitidas al objeto remoto a través de un canal que conecta los dos dominios de aplicación • El cliente sólo mantiene una referencia al objeto, no una copia del mismo
Conceptos Básicos • Como segundo paso en hacer un objeto remoto hay que registrar la clase para que pueda ser activada desde otro dominio de aplicación • Hay dos modos de registrar un objeto, a través de dos métodos estáticos en System.Runtime.Remoting.RemotingConfiguration: • RegisterActivatedServiceType • RegisterWellKnownServiceType RemotingConfiguration.RegisterWellKnownServiceType ( typeof(RemotableClass), // Remotable class “RemoteObject”, // URI of remotable class WellKnownObjectMode.SingleCall // Activation mode );
Tipos de objetos remotos (Según sea su modelo de activación ). • Antes de poder utilizar un objeto remoto este debe ser creado e inicializado, en un proceso llamado activación. • La activación puede ser de varios tipos: • Hay dos modos de activar un objeto en la parte servidora: • WellKnownObjectMode.SingleCall, crea una nueva instancia de RemotableClass por cada llamada invocada por un cliente • WellKnownObjectMode.Singleton, crea una instancia de RemotableClass para procesar todas las llamadas de los clientes • Cliente
Conceptos Básicos • Para hacer que la clase RemotableClass sea accesible por clientes remotos, el proceso servidor tiene que crear y registrar un canal (channel) • Un canal provee un conducto para la comunicación entre un objeto y un cliente remoto • .NET ofrece dos tipos de canales: • System.Runtime.Remoting.Channels.Tcp.TcpServerChannel acepta conexiones TCP de clientes remotos • Es el más eficiente • System.Runtime.Remoting.Channels.Http.HttpServerChannel, que acepta conexiones HTTP • Permite usar IIS como agente de activación TcpServerChannel channel = new TcpServerChannel(1234); ChannelServices.RegisterChannel(channel);
Conceptos Básicos • Una aplicación cliente que quiera crear una instancia remota de RemotableClasss tiene que registrarse por su parte • Hay dos tipos de canales para clientes: • HttpClientChannel-> permite a un cliente hablar con un servidor que escucha en un HttpServerChannel • TCPClientChannel -> permite a un cliente hablar con un servidor que escucha en un TCPServerChannel • Si el cliente quiere usar new para instanciar un objeto remoto, debe registrar la clase remota en el dominio de aplicación local • RegisterWellKnownClientType registra una clase en el cliente que está registrada como RemotingConfiguration.RegisterWellKnownServiceType en el servidor:
Conceptos Básicos • Para que un Cliente se pueda comunicar con un objeto remoto necesitamos un camino a través del que se pueda realizar la transferencia de datos. Este camino se llama canal (Channel). Un canal toma datos, crea un paquete según las especificaciones de un protocolo y envía el paquete a otro ordenador. • Los canales son utilizados para transportar los mensajes desde y hacia los objetos remotos. Cuando un cliente invoca remotamente un método, los parámetros y otros detalles referidos a la invocación son transportados a los objetos por medio del canal. De la misma forma son transportadas las respuestas a esa invocación.
Canales • Dos tipos de canales HTTP ó TCP. • Canales TCP: Usan TCP para comunicarse y transmiten datos en formato binario. Son adecuados cuando el rendimiento es lo importante. • El canal TCP tiene un rendimiento mayor ya que se conecta directamente a un puerto seleccionado por nosotros. • Canales http: Usan HTTP para comunicarse. Lo más normal es que transporten mensajes de tipo SOAP. Son adecuados cuando lo que prima es la interoperabilidad. • El canal HTTP es comúnmente utilizado para las comunicaciones en Internet.
SOAP • Simple Object Access Protocol • Gran parte de la capacidad de .NET Remoting para operar con diferentes entornos reside en SOAP. • Aunque no es el protocolo más eficiente, permite gran flexibilidad. • SOAP es un protocolo basado en XML que especifica un mecanismo mediante el cual aplicaciones distribuidas pueden intercambiar información independientemente de la plataforma • Aunque SOAP utiliza HTTP para su transporte, SOAP podría utilizar cualquier protocolo de transporte (pe SMTP). • http://www.w3.org/TR/SOAP/.
Conceptos básicos TcpClientChannel channel = new TcpClientChannel(); ChannelServices.RegisterChannel(channel); RemotingConfiguration.RegisterWellKnownClientType( typeof(RemotableClass), // Remotable class “tcp://localhost:1234/RemoteObject” // URL of remotable class ); • Una vez que el cliente y el servidor han efectuado sus registros correspondientes se crea la instancia de RemotableClass: RemotableClass rc = new RemotableClass();
Tu primera aplicación con .NET Remoting • Aplicación que devuelve a clientes remotos la hora del sistema • Tres componentes: • Una DLL llamada ClockServer.dll que contiene la clase Clock • Un servidor llamado TimeServer.exe que registra Clock para la activación remota • Un cliente (TimeClient.exe) que activa Clock remotamente
ClockServer.cs using System; public class Clock: MarshalByRefObject { public string GetCurrentTime() { return DateTime.Now.ToLongTimeString(); } }
TimeServer.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; class MyApp { static void Main() { // tcp://localhost:1234/Clock TcpServerChannel channel = new TcpServerChannel(1234); ChannelServices.RegisterChannel(channel); RemotingConfiguration.RegisterWellKnownServiceType( typeof(Clock), "Clock", WellKnownObjectMode.SingleCall); Console.WriteLine("Press Enter to terminate ..."); Console.ReadLine(); } }
TimeClient.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; class MyApp { static void Main() { TcpClientChannel channel = new TcpClientChannel(); ChannelServices.RegisterChannel(channel); RemotingConfiguration.RegisterWellKnownClientType( typeof(Clock), "tcp://localhost:1234/Clock"); Clock clock = new Clock(); Console.WriteLine(clock.GetCurrentTime()); } }
Compilando y ejecutando ejemplo Clock • Para compilar ClockServer.dll, TimeServer.exe y TimeClient.exe: • csc /t:library clockserver.cs • csc /r:clockserver.dll TimeServer.cs • csc /r:clockserver.dll TimeClient.cs • Empieza en una nueva consola para el servidor: start TimeServer.exe • Haz lo mismo para el cliente: start TimeClient.exe • Obsérvese que si se desea que el cliente y el servidor estén en diferentes máquinas entonces será necesario copiar ClockServer.dll al cliente, ya que para construir el proxy .NET extrae metadata de ClockServer.dll
Configuración Declarativa • Las clases TimeServer y TimeClient usan información embebida en el código para registrar canales y clases remotas • El problema es que si deseamos cambiar algún detalle hay que recompilar • El registro declarativo toma información de un fichero CONFIG y se activa llamando al método estático RemoteConfiguration.Configure • Para modificar el cliente para activar el objeto Clock en otra máquina es tan sencillo como editar el fichero TimeClient.exe.config • La información a cambiar no es modificable por cualquier usuario y además se puede borrar accidentalmente • Elegir entre registro declarativo o programático depende de que es más importante si conveniencia o robusted.
ClockServer.cs using System; public class Clock : MarshalByRefObject { public string GetCurrentTime () { return DateTime.Now.ToLongTimeString (); } }
TimeServer.cs using System; using System.Runtime.Remoting; class MyApp { static void Main () { RemotingConfiguration.Configure ("TimeServer.exe.config"); Console.WriteLine ("Press Enter to terminate..."); Console.ReadLine (); } }
TimeServer.exe.config <configuration> <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" type="Clock, ClockServer" objectUri="Clock" /> </service> <channels> <channel ref="tcp server" port="1234" /> </channels> </application> </system.runtime.remoting> </configuration>
TimeClient.cs using System; using System.Runtime.Remoting; class MyApp { static void Main () { RemotingConfiguration.Configure ("TimeClient.exe.config"); Clock clock = new Clock (); Console.WriteLine (clock.GetCurrentTime ()); } }
TimeClient.exe.config <configuration> <system.runtime.remoting> <application> <client> <wellknown type="Clock, ClockServer" url="tcp://localhost:1234/Clock" /> </client> <channels> <channel ref="tcp client" /> </channels> </application> </system.runtime.remoting> </configuration>
Server Activation vs. Client Activation • Hay dos tipos de objetos remotos: • Server-activated objects • Se registran con RegisterWellKnownServiceType y RegisterWellKnownClientType • Cuando el cliente invoca new sólo se crea un proxy, el objeto no se crea hasta que una invocación es recibida • Sólo se pueden usar constructores por defecto sin parámetros • Client-activated objects • Se registran con RegisterActivatedServiceType y RegisterActivatedClientType • El objeto remoto se crea en la parte servidora inmediatamente después de llamar a new • Se pueden activar con constructores con parámetros
Server Activation vs. Client Activation • Cuando registras un objeto activado en la parte servidora se especifica como modo de activación: • WellKnownObjectMode.SingleCall, que crea una única instancia de un objeto por cada petición • WellKnownObjectMode.Singleton, que crea una única instancia y la usa para servir peticiones • Permite mantener estado entre invocaciones • No sincroniza las llamadas invocadas sobre métodos • Los objetos activados en la parte del cliente ofrecen otro modo de activación • Cada llamada a new por un cliente crea una instancia que preserva estado de una llamada a otra. • Si quieres mantener estado por cada cliente deberás utilizar este modo de activación. • Ejemplo StopWatch ilustra el uso de client-activated objects
Stopwatch.cs using System; public class Stopwatch : MarshalByRefObject { DateTime mark = DateTime.Now; public void Start () { mark = DateTime.Now; } public int Stop () { return (int) ((DateTime.Now - mark).TotalMilliseconds); } }
StopWatchServer.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; class MyApp { static void Main () { TcpServerChannel channel = new TcpServerChannel (1234); ChannelServices.RegisterChannel (channel); RemotingConfiguration.RegisterActivatedServiceType (typeof (Stopwatch)); Console.WriteLine ("Press Enter to terminate..."); Console.ReadLine (); } }
StopWatchClient.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; class MyApp { static void Main () { TcpClientChannel channel = new TcpClientChannel (); ChannelServices.RegisterChannel (channel); RemotingConfiguration.RegisterActivatedClientType (typeof (Stopwatch), "tcp://localhost:1234"); Stopwatch sw = new Stopwatch (); sw.Start (); Console.WriteLine ("Press Enter to show elapsed time..."); Console.ReadLine (); Console.WriteLine (sw.Stop () + " millseconds"); } }
Pasando Objetos con .NET Remoting • Puede darse el caso de que algún parámetro de entrada o salida de algún método de nuestro objeto remoto sea un objeto. • En el caso que el objeto sea pasado por valor el marco de Remoting se encarga de hacer una copia completa del objeto para que pueda ser enviado a través de un canal. En el .NET Framework existen los formateadores de serialización que se encargan de codificar y decodificar los mensajes. • .NET, binario (System.Runtime.Serialization.Formatters.Binary) • SOAP (System.Runtime.Serialization.Formatters.SOAP). • A los objetos que contengan mayor cantidad de información, será adecuado pasarlos por referencia.
Los métodos Activator.GetObject y Activator.CreateInstance • Un objeto no sólo se puede activar a través del operador new • A través de los siguientes métodos estáticos definidos en System.Activator también se pueden registrar objetos: • GetObject se usa para activar objetos en la parte servidora • CreateInstance se usa para activar objetos en la parte cliente • Además en la parte cliente ya no es necesario usar RegisterActivatedClientType o RegisterWellKnownClientType
Los métodos Activator.GetObject y Activator.CreateInstance • Ejemplo (antes): RemotingConfiguration.RegisterWellKnownClientType(typeof(Clock), “tcp://localhost:1234/Clock”); Clock clock = new Clock(); RemotingConfiguration.RegisterActivatedClientType(typeof(Stopwatch), “tcp://localhost:1234”); Stopwatch sw = new Stopwatch(); • Después: Clock clock = (Clock)Activator.GetObject(typeof(Clock), “tcp://localhost:1234/Clock”); object[] url = {new UrlAttribute(“tcp://localhost:1234”)}; Stopwatch sw = (Stopwatch)Activator.CreateInstance(typeof(Stopwatch), null, url); • ¿Por qué usar GetObject o CreateInstance? • Porque pueden usarse para activar un objeto remoto sin poseer otro conocimiento de ese objeto aparte de la url y una interfaz que soporta el tipo Iclock ic = (Iclock)Activator.GetObject(typeof(Iclock), “tcp://localhost:1234/Clock”);
Usando Interfaces para Declarar Contratos en Remoting I // csc /t:library IClock.cs public interface IClock { string GetCurrentTime(); } // csc /t:library /r:IClock.dll ClockService.cs using System; public class Clock : MarshalByRefObject, IClock { public string GetCurrentTime () { return DateTime.Now.ToLongTimeString (); } }
Usando Interfaces para Declarar Contratos en Remoting II // csc /r:ClockService.dll;IClock.dll TimeServer.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; class MyApp { static void Main() { RemotingConfiguration.Configure ("TimeServer.exe.config"); Console.WriteLine("Press Enter to terminate ..."); Console.ReadLine(); } }
Usando Interfaces para Declarar Contratos en Remoting III // TimeServer.exe.config <configuration> <system.runtime.remoting> <application> <service> <wellknown mode="SingleCall" type="Clock, ClockService" objectUri="Clock" /> </service> <channels> <channel ref="tcp server" port="1234" /> </channels> </application> </system.runtime.remoting> </configuration>
Usando Interfaces para Declarar Contratos en Remoting IV // csc /r:IClock.dll TimeClient.cs using System; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; class MyApp { static void Main() { RemotingConfiguration.Configure ("TimeClient.exe.config"); WellKnownClientTypeEntry[] serviceMetadata = RemotingConfiguration.GetRegisteredWellKnownClientTypes();
Usando Interfaces para Declarar Contratos en Remoting V if (serviceMetadata.Length > 0) { IClock clock = (IClock)Activator.GetObject(typeof(IClock), serviceMetadata[0].ObjectUrl); while (true) { Console.WriteLine(clock.GetCurrentTime()); } } } }
Usando Interfaces para Declarar Contratos en Remoting VI <configuration> <system.runtime.remoting> <application> <client> <wellknown type="IClock, IClock" url="tcp://localhost:1234/Clock" /> </client> <channels> <channel ref="tcp client" /> </channels> </application> </system.runtime.remoting> </configuration>
Ciclo de vida de objetos y leasing • En DCOM un objeto es destruido cuando su contador de referencias alcanza el valor 0 • En .NET: • Los objetos single-call server-activated viven por la duración de una llamada, luego pueden ser reclamados por el garbage collector • Los objetos singleton server-activated o client-activated trabajan de manera diferente: • Su duración de vida es controlado por leases que pueden ser manipulados programática o declarativamente. • Un lease es un objeto que implementa la interfaz ILease: • InitialLeaseTime: cuánto vive el objeto sin recibir una llamada • RenewOnCallTime: a cuánto se actualiza el lease cada vez que se recibe una llamada • CurrentLeaseTime: cuánto queda antes que se desactive el objeto • Por defecto: InitialLeaseTime (5 mins), RenewOnCallTime (2 mins) • Si un objeto no se llama en los primeros 5 minutos o en 2 minutos después de haberse invocado por última vez se reciclaría • Los valores por defecto pueden ser cambiados: • Especificando tiempos de leasing en un fichero de configuración • Sobreescribiendo MarshallByRefObject.InitializeLifetimeService en la clase remota
Ciclo de vida de objetos y leasing • Ejemplo fichero CONFIG: • Inicializa InitialLeaseTime y RenewOnCalltime a 20 y 10 minutos respectivamente • M significa minutos, D días, H horas, S segundos y MS milisengundos • Un número si sufijo indica segundos • El proceso servidor debe registrar el fichero con RemotingConfiguration.Configure <configuration> <system.runtime.remoting> <application> <!–- colocar después de elemento channels --> <lifetime leasetime=“20M” renewOnCallTime=“10M”/> </application> </system.runtime.remoting> </configuration>