He seguido dándole vueltas al asunto de mejorar el rendimiento de la aplicación.
Una solución más inmediata sería hacer que en lugar de cargar las ER según un orden aleatorio, sería ideal hacerlo según el orden de dependencia. Puesto que en este momento, antes de cargar las ER en el autómanta, realiza un grafo de dependencias, simplemente sería usar esta información para ordenar la carga. De esta manera se minimizan las esperas de los hilos de cada ER a cargar.
Otra solución a parte de esta es otra muy radical: programación distribúida (RMI) y programación orientada a aspectos (aspectj).
No voy a explicar en profundidad en qué consiste, entre otras cosas porque aún estoy asimilando conceptos.
Con RMI puedo descomponer la aplicación en servicios y clientes que se intercambian objetos remotos. Cada servicio y cliente se puede ejecutar en un ordenador distinto.
Con Aspecj puedo modular más aún el código teniendo en cuenta los aspectos, por ejemplo, abtrayendo la distribución o la sincronización.
Esta nueva versión del código será una combinación de ambas tecnologías.
En este momento sólo tenemos una gran estructura de datos y dentro de ésta está el diccionario de cadenas, el autómanta, el diccionario de nombres del autómata, el diccionario de ER, el grafo de dependencias... Todas las subestructuras están conectadas a las demás. Creo que precisamente por esa dependencia dificulta el paralelismo de los hilos. Ahora la idea es crear un servidor para cada estructura mencionada y especializarla esclusivamente para ello. Además de estos sercicios habrá otro más, el servicio coordinador. No voy a programar los servicios/clientes como aplicaciones por separados. Todo va a formar parte de la misma aplicación y ésta podrá unas veces trabajar como servidor del grafo de dependencias y en otras como cliente del diccionario de nombres del autómatas por ejemplo, para ello debe de haber un servicio que coordine todos los servicios y clientes en todos los ordenadores que estén conectados y compartiendo objetos a través de la red.
El caso más simple es teneniendo sólo un computador trabajando: lanzamos la aplicación con la IP y el puerto del servidor de la base de datos (que puede estar en el mismo pc o en otro). Al ser sólo un pc, él mismo es servidor y cliente de todos los servicios. Es decir, intercambia los objetos a nivel local entre los distintos módulos.
Ahora empezamos a conectar más pc y corremos la aplicación en cada uno de ellos: el pc anterior toma el control conviertiéndose en el servidor coordinador y su misión será la de repartir el trabajo entre los ordenadores conectados. En el mejor de los casos hay un pc por cada servicio. Al conectar/desconectar un pc, el pc coordiandor redistribuye la carga.
La idea es que no estén fijados los roles de los pc, sino que puedan cambiar. E incluso si el servidor coordinador (el primero el lanzarse) cae, asuma su papel otro pc.
Ahora los obejtos se intercambiarían remótamente.
Para aumentar de pcs la tarea es sencilla, pero al disminuir, se complica.
Si la salida de un pc es programada, es decir, el pc que abandona le comunica al servidor coordinador su intención, éste copiaría toda la estructura de datos del servicio/servicios que estuviera ofreciendo y lo asignaría a otro/otros pcs y a partir de este momento asumen esta nueva funcionalidad y los clientes ahora se dirigirán a ellos.
Si la salida no es programa, la cosa cambia. Al ser una aplicación que todos los datos procesados están en memoria (en uno o varios pcs de forma distribuida), si cae un servidor todos los datos de éste se pierden. Sin embargo, se puede remediar con servicios de réplica. Si cae un servicio automáticamente a sus clientes se les asigna la Ip del servidor copia y se le asignará a otro pc esa función y se le pasará toda la estructura para que ahora asuma el rol de réplica nuevo.
En el caso de no contar con réplicas no habrá otro modo que el de reiniciar todos los servicios vaciando sus datos y procesarlos desde el principio con los Pcs que hubiese tras la salida.
No hay comentarios:
Publicar un comentario