Title: Dise
1Diseño de Servidores
2Que es un Servidor
- Básicamente se puede definir como un proceso que
da un servicio - El servicio en general se describe por un
protocolo - Si es un servicio conocido (lisatado en la RFC
por la IETF, ver http//www.ietf.org) también
estará caracterizado por un port entre 1 y 1024 - Para contactar un servicio específico se requiere
saber (host, port, protocolo)
3Decisiones al diseñar un servidor
- Son realmente muchas y a todo nivel, por ejemplo
- qué tipo de comunicación uso
- con estado o sin estado
- iterativo o concurrente
- Lo programo yo mismo o uso algún soporte, por
ejemplo, servidor web, servidor de aplicaciones - si lo programo yo, uso algún tipo de middleware
- Las listadas acá se deberían tomar en ese órden
4Requerimientos
- Robusto
- Extrema tolerancia a fallas
- Tolerancia a clientes mal intencionados
- ver ejemplo de servidor de archivos robusto
- Redundancia?
- Cache de datos
- Eficiente con el uso de recursos
- Extendible
5Comunicación
- Orientado a la conexión
- brinda seguridad para la transmisión de datos
- lento, provoca congestión
- el más usado
- Sin conexión
- no garantiza seguridad
- rápido
- se usa en servidores de material pesado cuando
requiere de transmisión - Mensajes (con soporte)
6Servidores Con o sin Estado
- Qué es el Estado ?
- El estado es la información que los servidores
mantienen acerca de la interacción que se lleva a
cabo con los clientes. - Para qué ?
- Generalmente se hace más eficiente el
comporatamiento de los servidores con
información. Información muy breve mantenida en
el servidor puede hacer más chicos los mensajes o
permite producir respuestas más rápido. - Y entonces por qué se evita a veces ?
- Es fuente de errores mensajes del cliente pueden
perderse, duplicarse llegar en desorden. El
cliente puede caerse y rebootear, con lo cual la
información que tiene el servidor de él es
errónea y también sus respuestas
7Un ejemplo del servidor de Archivos
- El servidor espera que un cliente se conecte
por la red. El cleinte puede mandar 2 tipos de
requerimientos leer o escribir datos en un
archivo. El servidor realiza la operación y
retorna el resultado al cliente. - Situación sin guardar información acerca del
estado - Para leer, el cliente debe siempre especificar
nombre de archivo, posición en el archivo desde
dónde debe extraer los datos y el número de bytes
a leer. - Para escribir debe especificar el nombre completo
del archivo, el lugar donde quiere escribir y los
datos que quiere escribir
8Un ejemplo del servidor de Archivos (II)
- Situación guardardando información del estado
- Cuando el cliente abre un archivo se crea un
entrada en la tabla. A la entrada se le asigna un
handle para identificar el archivo y se le asigna
la posición actual (inicialmente 0). El cliente
recibe el handler como respuesta. - Cuando el cliente quiere extrer datos adicionales
le envia el handle y la cantidad de bytes. Esto
es usado por el servidor para saber gracias a la
tabla de dónde exactamente debe extraer los datos
(debe actualizar la posición para que para la
próxima vez se pueda hacer lo mismo). - Cuando el cliente termina la lectura/escritura
envía un mensaje para sea eliminada la entrada de
la tabla
9Otro ejemplo consulta bases de datos
- El cliente hace consultas a bases de datos.
En la primera consulta el resultado es muy
grande. Quiere refinar la consulta basada e los
resultados obtenidos hasta ahora - Situación sin guardar información acerca del
estado - El servidor debe mandar todo el resultado de la
consulta al cliente, el cliente debe mantenerla - El cliente debería ser capaz de hacer consultas
localmente o si no mandar la query con el
conjunto de resultados obtenidos la vez anterior
10Otro ejemplo carro de compras
- El servidor espera que un cliente se conecte
por la red. Consulte los productos que hay y vaya
seleccionando productos. El cliente se mueve
entre la búsqueda y la selección - Situación sin guardar información acerca del
estado - La lista completa de items seleccionada por el
cliente debe ser constantemente transmitida entre
cliente y servidor
11Otro ejemplo transacciones bancarias
- El servidor necesita que el cliente se
identifique con username y password para hacer
una transacción o consulta - Situación sin guardar información acerca del
estado - Por cada transacción que quiere hacer el cliente
se va a necesitar la información de
autentificación del cliente
12Problemas al mantener un estado
- En el servidor de Archivo ?
- En las consultas a una base de datos ?
- En un carro de compras ?
- En transacciones ?
13Servidores concurrentes e iterativos
- Un servidor iterativo atiende a los clientes 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 - 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 !
14Un servidor secuencial (iterativo) atendiendo a
más de un cliente
15Durante la conversación no puede oír por el
puerto 4444
16Sólo después de efectuar la transmisión se pone a
escuchar de nuevo por el 4444
17Si el servicio consiste en transferir un archivo,
el cliente debe digitar el nombre
18Qué sucede si el servidor tiene que esperar
mucho para que un cliente escriba el nombre de un
archivo?
19Un 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.
20Servidores Comcurrentes hay procesos separados
para atender el puerto y para transferir el
archivo
21Despué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
22Mientras el nuevo proceso está atendiendo al
primer cliente, el segundo cliente puede
contactar al servidor en el puerto 4444
23Y el servidor crea otro proceso
24Ahora un tercer cliente contacta al servidor
25Y un tercer proceso esclavo o thread es creado
26Algoritmo de Servidor Concurrente
- Programa principal o master del servidor
- 1. 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 !)
27Có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
28Ejemplo 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
-
29Problemas 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)
30En 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,
suspendido, 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).
31Usando 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
cualquier 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.
32Un ejemplo clásico de servidores un Servidor de
Archivos
Servicio de Directorio
Aplicación
Servicio plano de archivo (flat)
Módulo Cliente
33Componentes
- Flat File Service Implementa las operaciones
directamente sobre los archivos. Trabaja con
Unique File Identifieres (UFID). Se genera uno
nuevo por cada archivo - Directory Services Cliente de el FFS, provee un
mapeo entre los UFID y los nombre textuales de
los archivos y las funciones necesarias para
administrar directorios y obtener las UFID. Los
directorios se guardan como archivos planos. - Módulo Cliente Corre en cada computador, integra
y extiende las operaciones del FFS y DS en una
aplicación interfaz usada por los programadores.
Posee información acerca de la localización de
archivos en la red. Provee eficiencia a través de
un cache
34Modelo de Interfaz para FFS
- read(FileId, i, n) le hasta n bytes de un
archivo a partir de la posición i los que retorna
en un arreglo - write(FileId, i, Datos) escribe la secuencia de
datos en el archivo a partir de la posición i
extendiéndolo en caso - create() crea un archivo nuevo de largo 0 y
devuelve el UFID para él - delete(FileId) borra el archivo
- getAttributes(FileId) retorna una estructura
con los atributos - setAttributes(FileId, attr) pone los atributos
según la estructura
35Controles de acceso
- En un sistema local el chequeo se hace sólo al
abrir el archivo y los derechos se conservan - en un sistema distribuido los chequeos se deben
hacer a nivel de servidor. Para que el servidor
siga siendo stateless se pueden usar 2
estrategias - El chequeo se hace cuando el nombre es convertido
en UFID y el resultado es codificado en forma de
capacidad que se retorna al cliente, el cual lo
usa para futuros accesos - La identificación del usuario se hace cada vez
que se manda un request y el chequeo se hace para
cada operación - El segundo es más usado (en NFS y AFS) por su
simplicidad, pero ninguno garantiza seguridad en
el caso de identidad suplantada
36Modelo de interfaz para Directory Service
- Lookup(Dir, File) localiza el nombre de texto en
el directorio y retorna el UFID - AddName(Dir, Name, File) Si Name no estaba en el
directorio dado añade el par (Name,File) en el
directorio modificando el archivo pertinente - UnName(Dir, Name) el par (Name, file)
correspondiente es borrado del directorio - getNames(Dir) retirna la lista de nombres que
contiene un directorio
37Ejemplo 1 el NFS
Aplicación
Sistema Virtual
Sistema Virtual
Server NFS
Sist Local
Sist Local
Client NFS
38Características de NFS
- La comunicación es por medio de RPC y es abierta
en el servidor, que reside en el kernel - La identificación de archivos es por medio de los
llamados file handters consistentes en - Filesystem identifier
- i-node number or file
- i-node gerneration number
- El estado se guarda en el cliente en un v-node
- Autentificación del cliente en cada llamada
mandando user ID y group ID - Los servicios de flat file y directory están
integrados - El servicio de mount provee un link a un sistema
remoto
39Cache en NFS
- Cache en Unix buffer cache, read ahead, delayed
write - Cache en Server datos de escritura se guardan en
memoria cache y son escritas antes del reply al
cleinte. En la versión 3 se guarda todo en cache
hasta que se recibe la operación commit para ese
archivo (buffer lleno o close) - Cache en el servidor resultados de read, write,
getattr, lookup y readdir se almacenan
localmente, lo cual puede introducir
inconsistencias en versiones en los distintos
clientes ya que escrituras de un cliente no se
actualizan en seguida en los otros. Los clientes
son entonces responsables de mantener
actualizados sus caches por medio de timestamps
Tc tiempo de la última actualización, Tm tiempo
de modificación. A un tiempo T el cache será
válido si (T - Tc lt t) o (Tmcliente Tmserver).
Normalmente 3-30 seg para archivos y 30-60 para
directorios
40Ejemplo 2 El AFS
- Apunta a lograr mejor performance en situaciones
de escalabilidad - Whole-file serving El contenido de todo los
directorios archivos son traspasados al cleinte - Whole-file caching Los archivos transmitidos son
guardados en cache local. Normalmente varios
cientos de archivos ! El cache es casi
permanente. - Cuando se hace un open del archivo se transmite
el archivo entero si no estaba - las operaciones de escritura/lectura se hacen
localmente - Con el close, se transmite una copia modificada
al servidor - Debe
41Consistencia del Cache
- Cada vez que se traspasa un archivo del servidor
a un cliente se provee de una promesa de
callback, que garantiza que cuando otro cliente
modifique el archivo este será notificado - El callback puede estar en dos estados valido o
cancelado - Cuando el archivo es traspasado al cliente el
callback se pone en válido. Cuando se recibe un
callback del servidor (porque el archivo fue
modificado) se pone en cancelado - Cada vez que el cliente abre un archivo busca si
está en su cache. Si está se revisa el callback.
Si está cancelado se trae una copia nueva del
archivo, si está válido, se usa el archivo del
cache - Si la estación de trabajo se reinicia (por que se
apagó o se cayó) pide para cada archivo de su
cache el timestamp de la última modificación - si la última modificación es consistente con la
copia se pone el callback en válido, si no en
cancelado