Tema II.
Ambientes Distribuidos.
1. Ambientes distribuidos
Un sistema distribuido es un conjunto de componentes de hardware y software heterogeneos y
localizados que colaboran entre si para dar la imagen de que es un módulo unico, de una
manera transparente, confiable y tolerante a fallas.
Existen varios modelos de procesamiento en ambientes distribuidos.
Cliente/Servidor, que implica un módulo que procesa peticiones (el servidor) y un módulo
cliente que genera peticiones.
Procesamiento paralelo y masivo. Existe un modulo maestro que dicta ordenes a muchos modulos
esclavos
Peer-to-Peer (P2P). La manera de procesar es que cualquier modulo de software puede fungir
como cliente o servidor, sin tener un papel unico, sino que puede tomar cualquier rol.
2. Cliente/Servidor y modelo de N capas
Un sistema cliente/servidor son entidades lógicas independientes y heterogeneas que operan en
conjunto a través de una red para realizar una tarea.
Un sistema cliente/servidor debe tener las siguientes características :
Servicio. Un servidor contiene un conjunto de operaciones para proveer un conjunto de
funcionalidades.
Recursos Compartidos. Un servidor atiende a muchos clientes al mismo tiempo
Protocolos asimétricos. Los clientes siempre inician el diálogo y los servidores
aguardan pasivamente las solicitudes.
Transparencia de ubicación. El servidor puede residir en cualquier nodo de procesamiento,
y los clientes no necesitan conocer la ubicación del servidor
Independencia del hardware o plataforma de software o sistema opertaivo.
Mensajes. El intercambio entre cliente y servidor se realiza por medio de solicitudes
y respuestas del servicio, en forma de mensajes
Escalable. Consiste en agregar de manera transparente hardware y software, sin afectar
a los clientes y servidores, y que de hecho sean capaces de detectar los cambios
Para que un cliente y servidor se comuniquen, necesitan de un conjunto de protocolos.
Tipicamente son protocolos que se encuentran en la capa de aplicación, apoyandose en
pilas como TCP/IP. Dichos protocolos, la implantación de los mismos y mecanismos intermedios
se denominan en conjunto como middleware.
La tecnología cliente servidor comenzo con la construcción de programas que utilizaban
sockets. En algunos casos, surgian protocolos estandarizados, como por ejemplo ODBC para
acceso a base de datos y en otros casos eran protocolos hechos a la medida.
El desarrollo basado en sockets es complejo y propenso a errores; dado que implica una
programación de bajo nivel.
De ahí se ingenió una tecnología en la cual se enunciaban procedimientos o funciones
que podian transformarse en servicios remotos. Esto origino al modelo de "llamadas a
procedimientos remotos" o RPC.
Esta tecnología, principalmente propuesta por el modelo distribuido de DCE (Distributed
Computer Environment) y ONC (Open Network Connectivity) fue utilizada por muchos
desarrolladores que comunicaban sistemas UNIX, o sistemas UNIX/Win32.
Se basaba en la siguiente filosofía:
======= ==========
Interfaz Compilador ------ Procedimiento cliente
Remota --------- IDL --------|
escrita ------ Procedimiento Servidor
en IDL
======== ===========
IDL. Interface Definition Language o Lenguaje de definición de interfases permite enunciar
procedimientos, indicando el nombre del procedimiento, parámetros de la rutina y valor
de retorno. Este lenguaje es completamente declarativo, y no indica COMO se implanta, solo
declara QUE es lo que hace el servicio
Compilador IDL se encarga de tomar un interfaz IDL y convertirla a un lenguaje como C,
C++, COBOL.
Procedimiento Servidor. Implantación de la lógica del servicio, el COMO de la interfaz.
En dicho procedimiento se incluye código fuente para manejar los servicios de red.
Procedimiento Cliente. Implantación de la lógica de peticiones, para invocar operaciones
del servicio. La interacción con los servicios de red se incluye como código fuente generado.
Con el código generado se construyen los programas ejecutables y se siguen los siguientes
pasos:
1. Anuncio del servidor y puesta en marcha del servidor. Tipicamente se asocia el servicio
con un nombre o alias, en un servicio de directorios
2. Puesta en marcha del cliente y Busqueda del servicio.
3. Alimentación de entrada utilizando la aplicación cliente.
4. Invocación del cliente al servicio.
5. Al invocar, los parámetros de la invocación se empaquetan en un formato estándar y
se aplica una petición al servidor
6. El servidor recibe la petición y desempaqueta los argumentos
7. Se entrega al código responsable para procesar la petición y entregar el resultado.
Este esquema evolucionó de tal manera que en lugar de utilizar lenguajes estructurados,
empezó a utilizar tecnología de objetos, donde se enunciaban interfases orientadas
a objetos. Esto llevo al surgimiento de objetos distribuídos, que consiste en ejecutar
métodos de objetos en distintos nodos de la red.
La tecnología de objetos distribuídos empezó con la tecnología CORBA (Common Object Request
Broker Architecture) que es el resultado de tratar de comunicar objetos distribuidos
con un protocolo estandarizado como IIOP (Internet InterObject Protocol).
Con el surgimiento de Java, los sistemas cliente/servidor evolucionaron de una manera
acelerada y surgieron tecnologías que juntaron las ideas de CORBA con las nuevas
capacidades de Java, principalmente la de generar código en el vuelo.
Al diseñar un sistema cliente/servidor, el arquitecto siempre se tiene que topar
con la decisión relacionada en donde ubicar los distintos componentes.
Esto lleva a identificiar los modelos de capas. El modelo C/S surgió con un modelo
de 2 capas, donde se tenía un FrontEnd y un servidor (tipicamente una base de datos).
Esto llevaba a que la lógica de procesamiento se tenía que cargar en cualquiera de
las dos capas.
El manejo de transacciones se volvió algo que lograba saturar a las bases de datos,
por lo que se establecio un modelo de una capa intermedia, los objetos del negocio,
encargados de llevar toda la lógica del sistema, un frontend y una base de datos.
Cuando surgió la tecnología de WWW, se integró una nueva capa, donde el navegador
de Internet podía fungir como un nuevo frontend, mas portable y ubicuo, y una capa
que procesaba peticiones de WWW.
Hoy en día han surgido nuevas capas, y de hecho, la creación del concepto de Servicios
de Web o Web Services ha permitido liberar aplicaciones del navegador de WWW, pero
bastante fáciles de contactar, gracias a estándares como XML.
3. Servicios de un ambiente distribuido
Un sistema ambiente distribuido siempre debe tener un conjunto de servicios
para lograr sus objetivos.
Servicios de comunicación. Pila de protocolos TCP/IP
Sistemas de mensajes. Llamadas a procedimientos remotos
Servicio de directorios. Permite asociar a recursos de cómputo heterogeneos,
un nombre homologado y estándar
Servicios de procesamiento de transacciones. Ayuda a manejar la consistencia,
concurrencia y atomicidad de una operación realizada por un servidor.
Servicios de manejadores de bases de datos
Servicios de manipulación de objetos distribuidos
Tecnologías ERP como flujos de trabajo, procesos, planeación, etc
4. Modelos de comunicación
4.1 Sockets
La manera como se comunican los módulos cliente/servidor estan basados en su mayoria
en Sockets.
Un socket es el modelo de comunicación de información, en el cual se transmiten datos
utilizando llamadas al sistema operativo. Por tanto, su manipulación es de muy bajo
nivel, de hecho se tiene que transmitir la información como flujos de bytes
(http://www.geocities.com/gusdelact/cib9112002/codigo/ServidorSocket.java)
El siguiente código muestra un programa servidor Java con sockets:
/************************************************************************************/
import java.net.*;
import java.io.*;
/**
*
* @author gustavo
*/
public class ServidorSocket {
/** Creates a new instance of ServidorSocket */
public ServidorSocket() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
ServerSocket serv =null;
try {
serv = new ServerSocket(9080);
Socket sock;
while ((sock=serv.accept()) != null) {
OutputStream out=sock.getOutputStream();
out.write((byte)'a');
out.close();
sock.close();
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
try {
serv.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
/************************************************************************************/
El programa crear un servidor de sockets utilizando una clase predefinida de Java, llamada
java.net.ServerSocket, aceptando peticiones en el puerto 9080. Proced a quedar en
un ciclo infinito, esperando conexiones, y por cada conexión que reciba, escribe una
letra 'a'.
El programa cliente, se conecta al servidor en el puerto 9080:
/************************************************************************************/
import java.net.*;
import java.io.*;
public class ClientSocket {
/** Creates a new instance of ClientSocket */
public ClientSocket() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
Socket sock = new Socket("localhost",9080);
InputStream in=sock.getInputStream();
System.out.println((char)in.read());
in.close();
sock.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/************************************************************************************/
En ambos programas, se tienen que manipular flujos o streams de bytes, usando las
clases java.net.InputStream y java.net.OutputStream
4.2 Invocaciones a métodos remotos.
El modelo de sockets lleva a una programación de bajo nivel, dado que se tiene que
considerar el intercambio de información como flujo de bytes.
Un modelo cliente/servidor debe orientarse a resolver problemas propios de ambientes
distribuidos.
Una manera de abstraer la invocación a servicios, es pensar a manera de invocaciones a objetos
distribuidos.
Un objeto distribuido es un módulo de software que tiene propiedades y métodos expuestos
o disponibles a un protocolo de comunicación.
Cuando el objeto distribuido expone sus métodos, los clientes lo invocan via llamadas
a metodos remotos.
En un modelo de invocaciones remotas se tiene un proceso o servicio que centraliza o
es el mediador entre una aplicación cliente y servidor. La función de dicho proceso es
otorgar un nombre a cada objeto distribuido y atender peticiones TCP que contienen el
protocolo de invocaciones remotas
4.3 Remote Method Invocation (RMI)
En el caso de Java, su modelo de invocaciones remotas es definidio por el protocolo RMI.
Remote Method Invocation permite construir objetos distribuidos Java
Para codificar un servicio basado en RMI, se crea primero una interfaz, que es la
definicion de los métodos que expone un servicio:
/************************************************************************************/
import java.rmi.*;
/** Remote interface.
*/
public interface Servicio extends java.rmi.Remote {
public int directiva() throws RemoteException;
}
/************************************************************************************/
En este caso, existe una interfaz Java que indica que existe un método denominado
directiva y el cual retorna un entero
Se debe crear un programa Java que implante la interfaz, es decir, de el codigo
para el método servicio
/************************************************************************************/
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.net.MalformedURLException;
/** Unicast remote object implementing remote interface.
*/
public class ServicioImpl extends java.rmi.server.UnicastRemoteObject implements cibernetica.Servicio {
/** Register ServicioImpl object with the RMI registry.
* @param name - name identifying the service in the RMI registry
* @param create - create local registry if necessary
* @throw RemoteException if cannot be exported or bound to RMI registry
* @throw MalformedURLException if name cannot be used to construct a valid URL
* @throw IllegalArgumentException if null passed as name
*/
public static void registerToRegistry(String name, Remote obj, boolean create) throws RemoteException, MalformedURLException{
if (name == null) throw new IllegalArgumentException("registration name can not be null");
try {
Naming.rebind(name, obj);
} catch (RemoteException ex){
if (create) {
Registry r = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
r.rebind(name, obj);
} else throw ex;
}
}
/** Main method.
*/
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
ServicioImpl obj = new ServicioImpl();
registerToRegistry("ServicioImpl", obj, true);
} catch (RemoteException ex) {
ex.printStackTrace();
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
public int directiva() throws RemoteException {
System.out.println("Sirviendo directiva");
return 1;
}
}
/************************************************************************************/
Lo importante a notar de este codigo es que el servicio al crearse, se registra con un
nombre en el servidor de RMI o rmiregistry, con el nombre de "ServicioImpl". El método
directiva retorna el valor de 1
Este programa al compilarlo, se debe dar un paso adicional, que generar una clase
ServicioImpl_Stub, que es código Java que maneja de manera automática el protocolo RMI
(y por ende Socketes) y procesa todas las peticiones del cliente
Este programa depende de otro programa, denominado rmiregistry, el cual queda activo
en un puerto TCP (tipicamente 1090) y que escucha peticiones de objetos cliente y servidor.
A un servidor le da la posibilidad de registrarlo con un nombre y lo invoca cuando un
cliente necesita obtener un servicio de él. A un cliente le provee todas las actividades
necesarias para contactarlo con el objeto distribuido.
El cliente es el siguiente:
/************************************************************************************/
import java.rmi.*;
public class Cliente extends Object {
/**
* @param args the command line arguments
*/
public static void main(String args[]) {
try {
System.setSecurityManager(new RMISecurityManager());
Servicio serv=(Servicio)Naming.lookup("//180.50.50.115:1099/ServicioImpl");
System.out.println(serv.directiva());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
/************************************************************************************/
Se puede observar que el clietne tiene que indicar la dirección IP del nodo donde reside
el servidor rmiregistry, y un URI, que indica el nombre del objeto distribuido, como
fue registrado ante el servicio de RMI. Al obtener una referencia (o handle) al objeto
distribuido, puede invocar los metodos como si fueran LOCALES.
En conclusion, RMI es un conjunto de clases, protocolos y programas Java que permiten
que una aplicacion Java se convierta en un objeto distribuido.
5. Java 2 Enterprise Edition (J2EE)
JavaSoft propone un modelo cliente/servidor en el cual los servicios anteriores son
implantados con lenguaje Java
4.1 Arquitectura J2EE.
Ver http://java.sun.com/j2ee/sdk_1.2.1/techdocs/guides/j2ee-overview/OverviewTOC.fm.html
mientras se completan estos apuntes
5. Servlets & JSP
Del modelo de N capas de un sistema cliente/servidor, una de las capas que permite establecer
una liga entre un frontend basado en un navegador de Internet y el servidor, es conocido
como la capa de WWW.
Dicho servicio está compuesto por programas que se integran con el servidor de WWW.
Una aplicación de este tipo, se conoce que es un CGI (Common Gateway Interface).
Un CGI es un programa que recibe datos de alimentación via protocolo HTTP, ejecuta
procesos o lógica, y a partir de eso, genera resultados, que retorna con protocolo HTTP, ya
sea que los datos esten en formato HTML u otro.
Existen varias soluciones para crear CGIs. Algunas son librerias o APIs que permiten construir
CGIs en lenguaje C,C++ o Perl. Tipicamente el modelo de estas librerias es lanzar un proceso
al sistema operativo (via la llamada fork() si se habla de UNIX)
Otras soluciones mas ligeras, integran librerias dinamicas al propio servidor de WWW. Esas
librerias dan la oportunidad de incorporar lenguajes hechos en lenguajes de tercera generación
o combinar HTML con lenguajes orientados a generar HTML Dinámico.
En el caso de Java, la solución propuesta es una tecnología denominada Servlets.
Un Servlet es una clase Java, que se ejecuta en un marco de trabajo o framework y cuya
función es atender, procesar y generar resultados usando el protocolo HTTP.
Un ejemplo de un servlet es la siguiente clase:
/*****************************************************************************************
* Hola.java
*
* Created on August 30, 2002, 12:41 PM
*/
import javax.servlet.*;
import javax.servlet.http.*;
/**
*
* @author gustavo
* @version
*/
public class Hola extends HttpServlet {
/** Initializes the servlet.
*/
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
/** Destroys the servlet.
*/
public void destroy() {
}
/** Processes requests for both HTTP GET
and POST
methods.
* @param request servlet request
* @param response servlet response
*/
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
response.setContentType("text/html");
java.io.PrintWriter out = response.getWriter();
/* output your page here*/
out.println("");
out.println("
GET
method.
* @param request servlet request
* @param response servlet response
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
processRequest(request, response);
}
/** Handles the HTTP POST
method.
* @param request servlet request
* @param response servlet response
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, java.io.IOException {
processRequest(request, response);
}
/** Returns a short description of the servlet.
*/
public String getServletInfo() {
return "Short description";
}
}
/*****************************************************************************/
Este programa, correctamente cargado a un servidor que soporta Servlets, debe imprimir
en el navegador de WWW, la palabra "hola mundo servlets".
Por ejemplo, es posible procesar todos los componentes de una forma HTML:
<% i++; %> <%= i %> |