Title: Arquitectura de Servidores
1Arquitectura de Servidores
- Servidores Concurrentes
- Servidores Iterativos
- Servidores con Estado
- Servidores sin Estado
2Qué 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 !
3Un servidor secuencial (iterativo) atendiendo a
más de un cliente
4Durante la conversación no puede oír por el
puerto 4444
5Sólo después de efectuar la transmisión se pone a
escuchar de nuevo por el 4444
6Si el servicio consiste en transferir un archivo,
el cliente debe digitar el nombre
7Qué sucede si el servidor tiene que esperar
mucho para que un cliente escriba el nombre de un
archivo?
8Un 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.
9Servidores Comcurrentes hay procesos separados
para atender el puerto y para transferir el
archivo
10Despué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
11Mientras el nuevo proceso está atendiendo al
primer cliente, el segundo cliente puede
contactar al servidor en el puerto 4444
12Y el servidor crea otro proceso
13Ahora un tercer cliente contacta al servidor
14Y un tercer proceso esclavo o thread es creado
15Algoritmo 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 !)
16Có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
17Ejemplo 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
-
18Problemas 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)
19En 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).
20Servidores Stateless vs. Stateful el problema de
lectura de un archivo remoto.
requerimiento abrir archivo XYZ
A CLIENT
A SERVER
?
Respuesta archivo XYZ existe y está listo
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
21Un servidor stateless (sin estado) implica que no
se acuerda de las peticiones anteriores
requerimiento leer bytes 0 a 49 de XYZ
A CLIENT
A SERVER
?
Respuesta el contenido en bytes
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
22El cliente debe proporcionar toda la información
de nuevo !
reuquerimiento leer bytes 50 a 99 de XYZ
A CLIENT
A SERVER
?
Respuesta el contenido en bytes
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
23This may cause a lot of network traffic,
especially if there are many clients
requerimiento leer bytes X a X50 de XYZ
A CLIENT
A SERVER
?
Respuesta el contenido en bytes
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
24Stateful Server mantiene alguna información de
lo que ha pasado
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
Pointer archi Posición
0 XYZ 0
1 ZXY 50
Req. abrir XYZ
A CLIENT
A SERVER
?
respuesta file pointer a XYZ
25La información que tiene que transmitir el
cliente es mucho menos
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
Pointer Archivo Posición
0 XYZ 50
1 ZXY 50
Req. 0, leer 50
A CLIENT
A SERVER
?
respuesta el contenido
26La información en la tabla debe ser actualizada
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
Pointer Archivo Posición
0 XYZ 100
1 ZXY 50
Req. 0, leer 50
A CLIENT
A SERVER
?
respuesta el contenido
27Es importante cerrar el archivo
Open file XYZ read first 50 bytes while (not end
of file XYZ) read next 50 bytes close file
Pointer Archivo Posición
0 XYZ 100
1 ZXY 50
Req. 0, leer 50
A CLIENT
A SERVER
?
respuesta el contenido
28Posibilidad de Errores
- La red manda dos veces el datagrama con
requerimiento de lectura - Si el computador del cleinte se cae y rebootea el
programa. - Si el computador se cae antes de poder
des-registrarse - Si otro cliente se conecta en el mismo port que
el que se cayó sin avisar - En una internet real, donde las máquinas
pueden caerse y rebootear y los mensajespueden
perderse, llegar atrasados, duplicados o en
orden incorrecto un servidor con manteción de
estado puede resultar difícil de programar para
hacerlo tolerante a los errores.
29Arquitectura de un Servidor de Archivos
Servicio de Directorio
Aplicación
Servicio plano de archivo (flat)
Módulo Cliente
30Componentes
- 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
31Componentes
- 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
32Modelo 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
33Controles 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
34Modelo 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
35Ejemplo 1 el NFS
Aplicación
Sistema Virtual
Sistema Virtual
Server NFS
Sist Local
Sist Local
Client NFS
36Caracterí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
37Cache 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
38Interfaz de NFS simplificada
- 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
39Ejemplo 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
40Esquema del AFS
Aplicación
Unix Kernel
Vice
Sist Local
Venus
Unix Kernel
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