PDF de programación - Curso 2014 3

Imágen de pdf Curso 2014 3

Curso 2014 3gráfica de visualizaciones

Publicado el 19 de Abril del 2017
712 visualizaciones desde el 19 de Abril del 2017
1,5 MB
15 paginas
Creado hace 9a (27/10/2014)
Introducción
En esta nueva práctica vamos a explorar el concepto de “modo de vida” de un objeto
remoto. Este concepto es fundamental para entender el funcionamiento del mismo y es
necesario para muchas de las decisiones de diseño y arquitectura de una aplicación
distribuida.

Existen varios modos de vida de los objetos remotos y cada middleware suele ofrecer
unos u otros pero todos ellos suelen ser variantes más o menos similares. Este
concepto no debemos confundirlo con el de “ciclo de vida” que también abordaremos
a lo largo de las prácticas.

Curso de Middleware. Práctica 3.

1 de 15

Jugando con el Objeto Remoto
Para seguir con nuestro trabajo, os recomiendo que hagáis copia de seguridad de lo
que ya tenemos desarrollado y sigamos trabajando sobre el código de nuestra práctica
anterior.
Sobre el código anterior vamos a añadir un poco de código a nuestra calculadora para
que nos permita guardar y recuperar un número. El cambio es rápido. Bastaría con
añadir el siguiente código a la calculadora:

public class Calculadora : System.MarshalByRefObject
{

private int dato = -1;

public void GuardarDato(int d)
{
dato = d;
}
public int ObtenerDato()
{
return dato;
}



public int Dato
{

get { return dato; }
set { dato = value; }

}

.. resto del código..
}

Además de los métodos para guardar o recuperar la información (“GuardarDatos” y
“ObtenerDatos”), hemos utilizado un atributo de C# (“Dato”). Un atributo en C# hace
la misma función que los get/set de Java. Permite recubrir una variable para controlar
el acceso. También permite disfrazar de variable una función. Es un concepto muy
potente y merece la pena conocerlo. Consulta tu manual de C# al respecto.
Y ahora añadimos algunas llamadas a estos métodos desde nuestro cliente. Por
ejemplo, os propongo algo del estilo:


Curso de Middleware. Práctica 3.

2 de 15

public static void Main(string[] args)
{
// código antiguo ...
Console.WriteLine("Creando la calculadora");
Calculadora calc = new Calculadora();

Console.WriteLine("El valor del dato al principio =" +
calc.ObtenerDato());

Console.WriteLine("Voy a guardar 10 en el dato.");
calc.GuardarDato(10);
Console.WriteLine("Ahora, el valor del dato es =" +
calc.ObtenerDato());

// el resto del código antiguo iría aquí
}

No parece muy complicado, verdad? Realmente lo único que hacemos es preguntar
por el valor de una variable, la cambiamos posteriormente y volvemos a comprobar
que el valor se ha almacenado correctamente. Seguramente hayamos hecho cosas
parecidas infinidad de veces.
¡Es importante que lo pruebes!. No sigas hasta haber conseguido esta parte!.

Prueba primero en una arquitectura no distribuida y seguidamente vuelve a probar con
el ejemplo cliente/servidor. Recuerda que si comentas la línea en la que configuras
Remoting del cliente, pasas a modo no distribuido. En mi caso, he obtenido lo
siguiente cuando la aplicación era local:

Curso de Middleware. Práctica 3.

3 de 15

Ahora volvemos a descomentar la línea de configuración de Remoting en el cliente
para volver a tener un funcionamiento distribuido. En caso, yo he obtenido lo
siguiente:


¿Has obtenido el resultado que esperabas? Seguramente no, verdad?.
Si observamos la traza generada, el sistema nos dice que el valor del dato después de
haberlo cambiado por 10 …. !Sigue siendo -1!!!.
¿Cómo es posible que suceda esto?. Debería valer 10, no?
Vamos a descubrir qué está pasado y las razones que hay detrás de este
comportamiento tan confuso. Para ello intenta lo siguiente.
Define un constructor para la calculadora (no te olvides que debe ser público) y pon
una traza indicando que has pasado por allí. Por ejemplo, prueba con algo similar a:

...
public Calculadora()
{

Calculadora");
}
...

Console.WriteLine("Estoy en el constructor de la

Ahora, vuelve a comparar el funcionamiento entre la aplicación local y la aplicación
distribuida. ¿Obtenemos los mismos resultados?.
En mi ejemplo, yo he obtenido con la aplicación local (comentando la línea de
configuración) lo siguiente:

Curso de Middleware. Práctica 3.

4 de 15

y con la aplicación en modo distribuida:

Si has realizado los mismos pasos, podrás observar que en el servidor se llama al
constructor de la calculadora TRES VECES!!. Una vez por cada cada llamada a los
métodos. Pero lo más asombroso es que no hay NINGUNA llamada al constructor en
el cliente. En cambio, el cliente hace un “new Calculadora()”, por lo que deberíamos
esperar al menos una traza generada por el constructor.
Para estar seguros, os propongo que definamos una variable estática que se incremente
en el constructor. Ese valor lo podemos guardar como identificador de la calculadora.
Imprime en la trazas del constructor y de los métodos ese identificador. Pregunta si

Curso de Middleware. Práctica 3.

5 de 15

tienes dudas de como funciona una variable estática (también se denomina variable de
clase). El código que os propongo sería similar a éste:

...
public class Calculadora : System.MarshalByRefObject
{
private static int contador = 0;
private readonly int miID;

private int dato = -1;

public Calculadora()
{
miID = contador++;
Console.WriteLine("Estoy en el constructor de la
Calculadora. Mi Id =" + miID);
}

public void GuardarDato(int d)
{
Console.WriteLine("Estoy GuardarDato. Mi Id =" + miID);
dato = d;
}
public int ObtenerDato()
{
Console.WriteLine("Estoy ObtenerDato. Mi Id =" + miID);
return dato;
}
...

De nuevo, comparamos el funcionamiento tanto en local como en remoto. En local
veremos algo de este estilo:

Curso de Middleware. Práctica 3.

6 de 15

Efectivamente, cuando hemos ejecutado la aplicación en local, hemos visto que solo
se construía una calculadora y que ese ID era el mismo para todas las llamadas.
Ahora lo comprobamos en distribuido, y obtenemos algo similar a:

En este caso, vemos que cada llamada se ejecuta en una calculadora diferente (se
observan diferentes ID en las trazas).
Ejecuta varios clientes y varias veces con un mismo servidor (sin pararlo). Intenta
explicar el funcionamiento antes de continuar.

Curso de Middleware. Práctica 3.

7 de 15

La razón de que cada llamada cree un objeto remoto se debe a que hemos dicho en
nuestro fichero de configuración que el servicio era “ SingleCall”. Compruébalo en el
fichero de “App.config” del proyecto servidor.

...
<wellknown
mode="SingleCall"
type="Calculo.Calculadora, Calculo"
objectUri="Calculadora.remota"
/>
...

Este parámetro le indica al sistema que el objeto debe ser creado en cada llamada. El
sistema destruye el objeto al terminar la llamada. Suele ser útil cuando no interesa
mantener información entre llamadas.
La alternativa sería “Singleton” que indica que todas las llamadas se refieren al mismo
objeto. La vida del objeto (cuando se crea o hasta cuando existe) se define
combinando varias características y ésta es una de ellas. Probad a cambiar el modo de
activación y comprobad que las trazas se adaptan a ese nuevo modo.

...
<wellknown
mode="Singleton"
type="Calculo.Calculadora, Calculo"
objectUri="Calculadora.remota"
/>
...

Os adjunto de nuevo las trazas que he obtenido al cambiar la configuración por
“Singleton”. Dado que esta configuración solo se aplica a la configuración del
servidor, no tiene sentido volver a probar en modo local.

Curso de Middleware. Práctica 3.

8 de 15

Ahora parece que nuestro funcionamiento es el esperado. Verdad? ¿Realmente? ¿O
todavía tenemos alguna sorpresa más?
Si volvemos a lanzar un cliente (sin parar el servidor) veremos que el nuevo cliente
utiliza … la misma calculadora que el cliente anterior! Si lanzamos varios clientes
simultáneos, TODOS ellos están utilizando la misma calculadora. En una ejecución
con cuatro clientes yo he obtenido lo siguiente:

Quizás debamos reflexionar sobre lo que está sucediendo. Las cosas no parecen tan
evidentes cómo creíamos.
Lo que está sucediendo es que los objetos remotos “toman vida” de forma

Curso de Middleware. Práctica 3.

9 de 15

independiente a la vida que se observa localmente. La vida de nuestro objeto local
nace cuando hacíamos “Calculadora calc = new Calculadora();” y moría cuando se
cerraba su ámbito.
En cambio el objeto remoto puede tener modos de vida muy diferentes. Y es muy
común asociar estos modos de vida al estado que deseamos guardar en el servidor.
Aunque en .Net Remoting tengan los nombres de “SingleCall” o “Singleton”, en otros
middleware pueden tener otros nombres. Por ejemplo en JavaEE aparecen los
nombres “Stateful” y “Stateless”. Su significado es ligeramente diferente al que
hemos visto, pero reflejan el mismo concepto de que los objetos remotos tienen “vida
propia”. La totalidad de los middleware basados en objetos remotos tienen esta forma
de trabajar. Algunos de ellos son muy elaborados, otros muy sencillos y la gran
mayoría ofrecen alternativas para simular cualquier modo de vida que necesitemos.
Lo más complejo de esta práctica es aceptar que los objetos remotos tienen una vida
independiente del código del cliente. Es decir, los objetos remotos son construidos y
destruidos por el servidor que los aloja, siguiendo diferentes políticas. Estas políticas
definen cuándo un objeto debe ser construido, compartido y destruido.
Y que este funcionamiento tan extraño tiene sentido. Mucho sentido!.

Es un buen momento para que
  • Links de descarga
http://lwp-l.com/pdf3125

Comentarios de: Curso 2014 3 (0)


No hay comentarios
 

Comentar...

Nombre
Correo (no se visualiza en la web)
Valoración
Comentarios...
CerrarCerrar
CerrarCerrar
Cerrar

Tienes que ser un usuario registrado para poder insertar imágenes, archivos y/o videos.

Puedes registrarte o validarte desde aquí.

Codigo
Negrita
Subrayado
Tachado
Cursiva
Insertar enlace
Imagen externa
Emoticon
Tabular
Centrar
Titulo
Linea
Disminuir
Aumentar
Vista preliminar
sonreir
dientes
lengua
guiño
enfadado
confundido
llorar
avergonzado
sorprendido
triste
sol
estrella
jarra
camara
taza de cafe
email
beso
bombilla
amor
mal
bien
Es necesario revisar y aceptar las políticas de privacidad