Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo...

38
Servidores Concurrentes Capítulo 5

Transcript of Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo...

Page 1: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Servidores Concurrentes

Capítulo 5

Page 2: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor • Una forma es ir atendiéndolos de a uno en un ciclo: como en el

programa que atiende pedidos de archivos– Se acepta una conexión– Se lee la petición– Se lee desde el archivo y se escribe en el socket hasta encontrar

una marca de fin de archivo• A este tipo de servidores se les llama servidores iterativos• El problema es que todo cliente tiene que esperar su turno para

ser atendido• Si uno de ellos pide un archivo muy grande los demás tienen

que esperar• La mayor parte de la espera es debido a operaciones de IO, hay

capacidad de CPU ociosa !

Page 3: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Un servidor secuencial (iterativo) atendiendo a más de un cliente

A SERVERA CLIENT

A CLIENT

A CLIENT

4444

Page 4: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Durante la conversación no puede oír por el puerto 4444

A SERVERA CLIENT

A CLIENT

A CLIENT

4444

Page 5: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Sólo después de efectuar la transmisión se pone a escuchar de nuevo por el 4444

A SERVERA CLIENT

A CLIENT

A CLIENT

4444

Page 6: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Si el servicio consiste en transferir un archivo, el cliente debe digitar el

nombre

A SERVERA CLIENT

A CLIENT

A CLIENT

4444

Page 7: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

¿Qué sucede si el servidor tiene que esperar mucho para que un cliente escriba el nombre de un archivo?

A SERVERA CLIENT

A CLIENT

A CLIENT

4444Timeout

ArchServidor2

Page 8: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Un Servidor Concurrente • Un servidor concurrente atiende a varios clientes al

mismo tiempo.• Más aún, mientras está atendiendo sigue escuchando • El problema es que todo cliente tiene que esperar su

turno para ser atendido.• Si uno de ellos pide un archivo muy grande los

demás tienen que esperar• La mayor parte de la espera es debido a operaciones

de IO, hay capacidad de CPU ociosa!• Se trata de crear un nuevo proceso o línea de

ejecución cada vez que un cliente “llega” a pedir un servicio.

Page 9: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Servidores Comcurrentes: hay procesos separados para atender el puerto y para

transferir el archivo

A SERVER

A CLIENT

A CLIENT

A CLIENT

4444

Page 10: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Después que el cliente contacta al servidor, éste crea otro proceso para

para atender al cliente y se queda escuchando el puerto 4444 por otro

A SERVER

A CLIENT

A CLIENT

A CLIENT

4444

Page 11: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Mientras el nuevo proceso está atendiendo al primer cliente, el segundo cliente puede contactar al servidor en el

puerto 4444

A SERVER

A CLIENT

A CLIENT

A CLIENT

4444

Page 12: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Y el servidor crea otro proceso

A SERVER

A CLIENT

A CLIENT

A CLIENT

4444

Page 13: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Ahora un tercer cliente contacta al servidor

A SERVER

A CLIENT

A CLIENT

A CLIENT

4444

Page 14: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Y un tercer proceso esclavo o thread es creado

A SERVER

A CLIENT

A CLIENT

A CLIENT

4444

Page 15: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Algoritmo de Servidor Concurrente

Programa principal o “master” del servidor1. Crear un Socket de servidor

En un ciclo infinito:2. Aceptar requerimientos de clientes

3. Cuando llega una petición de un cliente crear un nuevo proceso “esclavo” que atienda paralelamente la petición (esto no debe bloquear la ejecución del programa master del servidor)4. Volver a 2.

Proceso esclavo:1. Recibir los parámetros de la comunicación (socket o flujos de entrada y/o salida)2. Atender al cliente (ej: leer el nombre del archivo, transmitir el archivo)3. Retornar (desaparecer !)

Page 16: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Cómo (y por qué) crear procesos paralelos

• Si existe sólo una CPU, ¿Por qué crear procesos paralelos?– Porque algunos programas se escriben más fácilmente así. De hecho, la

programación de un servidor es a veces más fácil si se hace de esta manera.

– Porque sí hay más de un procesador !!!!! (¿dónde?)• El concepto de procesos paralelos implentados a nivel de S.O.

aparecen con UNIX y C. • La forma de crearlos es ejecutando una función llamada fork()• int i = fork() provoca que se cree un proceso exactamente igual al

que se está ejecutando. • La única diferencia es que en el proceso hijo (el nuevo creado) la

variable i vale cero. Esto se usa para saber quién soy yo. • En programación de servidores concurrentes, si soy el hijo ejecuto la

parte que corresponde al proceso esclavo. • Si soy el padre (i tiene un valor distinto de cero y es el id del

proceso hijo creado) sigo recibiendo peticiones

Page 17: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Ejemplo de procesos paralelos en C (muy simplificado)

main() { int pid, msock, ssock; sock = passivesock(port, “tcp”, qlen); /* ver capítulo 10.4 del libro Internetworking with tcp/ip de Douglas

Commer para ver cómo se implementa */

while(1) { ssock = accept(msock, &fsin, &alen);

pid = fork(); if (pid == 0) { atender al cliente; retornar; } }

Page 18: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Problemas con el fork() en UNIX• La creación del proceso paralelo es costosa en tiempo.

– En algunos textos se sugiere que se podrían crear los procesos paralelos al levantar el servidor. Cuando llegue un cliente simplemente se le pasan los datos por medio de un pipe que se crea entre el proceso padre y el proceso hijo

• El proceso paralelo duplica exactamente todo el ambiente en el cual estaba corriendo el proceso original, incluso aquellas variables que no necesita !!!

• No es fácil manejar procesos paralelos, ya que si no se terminan en forma “normal” pueden quedar consumiendo recursos indefinidamente.

• La única información que tiene el padre para controlarlos es su identificación al crearlos.

• Muchas veces se prefiere usar el método select, que lo que hace es preguntar de una serie de puntos de lectura de datos (en este caso sockets) cuál está listo para ser leído: este puede ser uno de los sockets de comunicación con cliente (en un arreglo) o el socket por donde se escuchan las peticiones (recordar que el IO es lo más lento en todo esto)

Page 19: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

En JAVA se prefiere usar Threads • Un thread es una secuencia o flujo de de instrucciones que

se ejecutan dentro de un programa. Tiene un comienzo y un fin. Entonces qué diferencia tiene con un proceso?

• El thread sólo puede ser creado dentro de un proceso. Y un proceso (programa) puede crear varios threads dentro de él que se ejecutan en paralelo.

• Entonces, qué diferencia tiene con el fork(). El programa principal está “conciente” de los threads que existen, hay variables que los identifican. Pueden ser creados, inicializados, sustendidos, reactivados o parados por el el programa que los creó.

• El programa principal puede darles parámetros distintos a cada thread. Los thread se pueden programar con la canatidad de variables necesarias para su ejecución (no lo heredan TODO).

Page 20: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Usando threads para atender multiples clientes de un Servidor de Sockets

• La forma de implementar servidores que atiendan a varios clientes paralelamente a la vez es combinando threads con sockets.

• El servidor abre un ServerSocket desde donde oye ciualquier intento por conectarse con él de un cliente.

• Una vez establecida la conexión, abre un socket normal e inicia un thread que atiende a este cliente. El socket abierto se pasa como parámetro. De esa manera puede seguir oyendo por el ServerSocket sin estar bloqueado.

• El thread tiene un método run que atiende los pedidos del cliente.

• El cliente se conecta al servidor sin saber que finalmente será un socket el que está atendiéndolo.

Page 21: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Implementación de Threads• Una forma de usar Threads en Java es creando una nueva

clase que extienda la clase Thread y sobreescribir el método run.– Los threads son una clase existente. Esta clase se debe extender

para hacer una clase derivada que haga lo que nosotros queramos.– Lo que un thread en particular hace cuando se echa a correr se

programa en un método llamado run de la clase extendida de Thread..

– El método run ejecuta cuando a un objeto de esta clase se le aplica el método start()

• El encabezado de una clase Thread será:– public class MiThread extends Thread {

• Y en alguna parte deberá aparecer– public void run() {

//aquí va lo que queremos que se haga en paralelo }

Page 22: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Ejemplo de Threads: escritura de la clase

public class SimpleThread extends Thread { public SimpleThread(String str) { super(str); }

public void run() { for (int i = 0; i < 10; i++) { System.out.println(i + " " + getName()); try { this.sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println("DONE! " + getName()); } }• El método this.sleep(milisegundos) debe ir en un bloque try and catch

Page 23: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Ejemplo de Threads: Uso de la clase nueva

public class TwoThreadsTest { public static void main (String[] args) { SimpleThread t1,t2;

t1 = SimpleThread("Jamaica"); t2 = SimpleThread("Fiji");

t1.start(); t2.start() } }• El método start() inicia la ejecucón de un thread.

Esto implica que se empieza a ejecutar el código escrito en el método run del thread. También existen otros métodos que se le pueden aplicar a un thread: suspend(), resume(), stop().

Page 24: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

A veces no se puede programar un servidor como una extensión de un

thread• Por ejemplo si necesita extender alguna otra clase como

applet o frame • Se puede usar la interfaz Runnable, lo que significa que la

clase deberá implementar el método run().• Para iniciar una ejecución paralela se crea un objeto

Thread y se le pasa como parámetro un objeto de la clase que implementó la interfaz

• Al ejecutar el método start() sonre un objeto thread creado de esta manera el método run implementado por el servidor

Page 25: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Ejemplo de interfaz con Runnable

• Veamos y ejecutemos el programa NoSincron.java

• Noten que los threads servidores creados de esta manera tendrán acceso a todos los recursos del programa que los creó.

• De la otra forma es más bien una opción, (pasar un puntero al servidor cuando se crea un objeto thread)

• De cualquier forma, será frecuente el compartir recursos y por lo tanto la admistración de ellos es importante

Page 26: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Regiones críticas y semáforos

• Java provee básicamente dos métodos para proveer acceso sincronizado (exclusión mutua) a regiones críticas– Se puede declarar todo un método como región crítica,

con lo cual sólo un thread tiene acceso a ella (ver sincron1)

– Se pueden usar los semáforos de un objeto, cualquiera (ver sincron2)

Page 27: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Cómo usar threads para hacer servidores concurrentes

• Hacer una clase Thread que tenga como variables de un objeto un socket y flujos de entrada y/o salida.

• Programar el constructor de modo que reciba como parámetro un socket y haga todo lo necesario para dejar inicializado el ambiente para empezar a atender al cleinte (por ejemplo, abrir flujos de datos de entrada y/o salida del socket recibido)

• Programar el método run de modo que implemente el protocolo necesario.

• Programar un método main que en un ciclo infinito se ponga a escuchar en un port dado la llegada de clientes.

• Con cada cliente nuevo crear un thread nuevo y pasar como parámetro el socket.

MultiFileServer MultiFileThread

Page 28: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Broadcasting a text to many clients

Hello

Hello

Hello

Hello

Hello

Hello

dos

Page 29: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

The server: receiving a new client

4444

Client contacts server at 4444

Page 30: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

The server: receiving a new client

4444

A new socket is placed and the output channel is opened They are kept in an array

Page 31: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

The server: Broadcasting a message

When the send button is pressedThe text of the TextField is retrievedAnd “printed” to all output streams

Message Test

Send

BroadcastCliente

BraodcastServer

Page 32: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Un Chat basado en TCP/IP

• Servidor: – un thread para oir clientes que se quieren conectar a la sesión y

un thread para recibir mensajes que deben ser repartidos y un thread para desconectarse

– un único thread para oir todos los mensajes provinientes del cleinte, al principio del mensaje viene descrito de qué tipo es el request

• Clientes:– un thread para mandar mensajes (puede ser el thread que atiende

los eventos de la interfaz) y otro para recibir mensajes mandados por el servidor

– Se necesitan clientes distintos para los distintos tipos de servidores (distinto protocolo !)

Page 33: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Un servidor web concurrente • En principio solo para archivos html y para clases, pero

extendible, por ejemplo, para procesar CGI o servlets• Para cada cliente que llega se crea un thread• Según el request se manda a procesar

HttpProcessorprocessRequest()

HttpFilebrowser

Httpd (servidor)

thread

HttpInputStream

HttpOutputStream

HttpClass

HttpException

Echo

HttpClassProcessor

Page 34: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Transmitiendo Objetos via TCP

• Transmisión: marshaling, delivery & unmarshaling. • La clave de esto es la serialización de objetos:

representar el objeto en un formato que pueda ser transmitido por la red (String)

• Todos los objetos nativos de java son serializables. • Para los objetos de clases definidas por los usuarios

basta declarar que implementan la interfaz Serializable (esto no incluye variables estáticas o referencias a cosas locales como archivos o sockets)

• con esto no hay implementar ningún método, esto lo hace automáticamente java

Page 35: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Transmitiendo Objetos via TCP• Clases que permiten la transmisión:

– ObjectInputStream readObjetct()

– ObjectOutputStream writeObject()

• El usuaio puede cambiar la forma “standard” del mecanismo de serialization que provee java declarando que la clase implementa la interfaz Externalizable

• Esto obliga a los usuarios a implementar los siguientes métodos – Void writeExternal(ObjectOutputStram o)

– Void readExternal(ObjectInputStream i);

Page 36: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Particularidades de TCP• Coincidencia de datos en los extremos :• Bloqueo: hay chequeo (ack) • Fallas : TCP trata de hacer coincidir las velocidades de escritura y lectura. Si el escribidor es muy rápido, trata de bloquearlo hasta que el lector haya consumido suficiente. • Duplicación y orden de mensajes: los paquetes ip contienen identificadores correlativos que permiten al recibidor detectar duplicados o cambiados de orden • Destino de los mensajes: como se abre una conexión virtual entre ambos extremos, no es necesario especificar a quién va ya que el socket se abre con un connect

Page 37: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Qué esconde TCP• Tamaño del mensaje: Las aplicaciones deciden cuánto leer y cuánto escribir. El sistema subyacente decide cómo transmitirlo.• Mensajes Perdidos: hay chequeo (ack) • Control de flujo: TCP trata de hacer coincidir las velocidades de escritura y lectura. Si el escribidor es muy rápido, trata de bloquearlo hasta que el lector haya consumido suficiente. • Duplicación y orden de mensajes: los paquetes ip contienen identificadores correlativos que permiten al recibidor detectar duplicados o cambiados de orden • Destino de los mensajes: como se abre una conexión virtual entre ambos extremos, no es necesario especificar a quién va ya que el socket se abre con un connect

Page 38: Servidores Concurrentes Capítulo 5. Qué pasa cuando varios clientes tratan de conectarse al mismo tiempo a un servidor Una forma es ir atendiéndolos de.

Problemas de TCP• Coincidencia de datos: Lo que se mande por un lado y lo que se lea (formato) debe coincidir (en especial al mandar objetos).• Bloqueo: hay que asegurarse que cundo se escribe pocos datos estos se manden si es necesario contar con ellos pronto o pueden bloquear la ejecución (buffer)• La comunicación se establece de punto a punto, así que sólo se atiende a un cliente a la vez (a menos que se haga concurrente)• Falla de la conexión: si se demora mucho en hacer el ack entonces la conexión se declara rota (se tira un IOException). En este sentido TCP no es más seguro de lo que la red lo es.• El proceso usando la conexión no puede distinguir si la falla se debe a la red o a que el proceso par se cayó• No puede saber después de la caída qué llego efectivamente a destino y qué no alcanzó a llegar