Default style (Cherry Eve). Switch styles (Capricorn). Atom Feed Calendar
http://weblogs.javahispano.org/amergin/date/20051231 sábado diciembre 31, 2005

¿Monitorización del host?

Hoy día, estamos muy acostumbrados a ver estadísticas sobre los recursos que utiliza nuestra máquina virtual, por ejemplo, mediante profiler como JProfiler, OptimizeIt, JProbe,.. o desde IDEs como NetBeans. Además la última moda, en gran medida gracias a Java 5, es mostrar en la propia aplicación el consumo de recursos. Un ejemplo curioso es el plugin disponible para Azureus.

Pues bien, el otro día, trabajando con el artículo "Using Aspect Oriented Programming to buils a portable load balancing service" los autores, muy razonablemente, afirman que las decisiones de balanceo deben estar dirigidas por los datos de monitorización del host como son:

  • Uso de CPU
  • Número de hilos/procesos ejecutándose
  • Memoria virtual usada, libre
  • Memoria física....
  • etc.

Problema: Monitorización del host. Si por el host consideramos la máquina virtual esta entrada en el blog debería terminar :-D. Hombre, en un entorno donde tenemos una máquina virtual en cada host y no hay ningún otro proceso "pesado" la simplificación JVM = host es muy asumible. En el caso de que tuviéramos más de una JVM en un mismo host y ningún otro proceso "pesado", se podría intentar calcular la carga del host en función de la suma de la carga de cada JVM. Pero... ¿y si nuestra máquina virtual comparte host con otros procesos no java?.

Imaginemos que tenemos un entorno académico donde se están constantemente realizando cálculos matemáticos para simulaciones. En varias máquinas hay procesos en C que calculan estructuras moleculares con grandes matrices que consumen mucha memoria. Y por supuesto, tenemos nuestro sistema distribuido que incorpora balanceo de carga. ¿Qué sucede cuando el host que esta ejecutando ese proceso en C envía sus datos de monitorización?. Pues si en ese momento en la máquina virtual solamente se está realizando la monitorización, nos dirá que el host no esta sobrecargado, y nada más alejado de la realidad.

Duda: ¿Cómo obtener información del host?, o mejor dicho, ¿seguro que eso es posible en java sin tener que recurrir a C?.

Un herramienta muy interesante que incorpora Java 5 es jconsole (Java Monitoring and Management Console). Aunque no se ha hablado mucho de ella parece ofrecer grandes posibilidades. Un ejemplo práctico de su uso puede verse en "Performance monitoring with AspectJ" (1) (2),

Sin perder de vista nuestro objetivo y siguiendo con la herramienta jconsole he encontrado un articulo "clave": "Using JConsole to Monitor Applications", del que especialmente me interesa el apartado Access OS resources-Sun's platform extension. Este artículo nos habla de la existencia de un Operating System MBean que es capaz de proporcionarnos la siguiente información:

  • El tiempo de proceso de la CPU
  • Memoria física libre y total
  • Memoria virtual libre y total
  • Memoria virtual comprometida (committed) que representa la cantidad de memoria virtual que estará disponible para el proceso de forma garantizada.
  • El número de descriptores de archivo abiertos (solamente en UNIX y derivados)
Bien, parece que existe algo :-D. Siguiendo la pista del OperatingSystemMXBean nos encontramos con lo siguiente:

La interfaz java.lang.management.OperatingSystemMXBean nos proporciona la siguiente información:

  • La arquitectura del sistema (x86,...)
  • Número de procesadores disponibles
  • Nombre del sistema operativo
  • Versión del sistema operativo

La interfaz com.sun.management.OperatingSystemMXBean nos proporciona la siguiente información:

  • Memoria virtual comprometida
  • Memoria física libre y total
  • Memoria virtual libre y total
  • Tiempo usado por nuestro proceso que esta ejecutándose en nuestra máquina virtual.

La interfaz com.sun.management.UnixOperatingSystemMXBean nos proporciona la siguiente información:

  • Número máximo de descriptores de archivo
  • Número de descriptores de archivo abiertos

Una vez que sabemos toda la información que podemos obtener la comparamos con lo que buscábamos y llegamos a las siguientes conclusiones: En cuanto a memoria del host tanto virtual como física tenemos el conocimiento deseado y suficiente como, por ejemplo, para alimentar el sistema de balanceo de carga. Sin embargo, en lo que respecta a consumo de CPU tenemos todos los datos relacionados con la JVM y el tiempo de procesador de nuestro proceso. Este último dato lo podríamos utilizar para hacer algún tipo de "adivinación".

Y cuando uno podría dar por perdido intentar saber la carga del procesador, aparece un Mustang y de él baja el método getSystemLoadAverage :-P. En Java 6 a la interfaz java.lang.management.OperatingSystemMXBean se le ha añadido este nuevo método que nos devuelve la carga del sistema en el último minuto.

Por último un pequeño ejemplo.


import java.lang.management.ManagementFactory;
import com.sun.management.OperatingSystemMXBean;

public class MonitorizacionHost {

    private long memFisicaTotal;
    private long memFisicaLibre;
    private long memVirtualTotal;
    private long memVirtualLibre;

    public MonitorizacionHost() {
    }

    public static void main(String[] args) {
        MonitorizacionHost monitor = new MonitorizacionHost();
        monitor.obtenerDatos();
        monitor.imprimirDatos();
    }

    private void imprimirDatos() {
        System.out.println("Informacion del sistema...\n");
        System.out.println("Memoria fisica total: " + memFisicaTotal);
        System.out.println("Memoria fisica libre: " + memFisicaLibre);
        System.out.println("Memoria virtual total: " + memVirtualTotal);
        System.out.println("Memoria virtual libre: " + memVirtualLibre);
    }

    private void obtenerDatos() {
        OperatingSystemMXBean mxbean = (OperatingSystemMXBean) ManagementFactory
                .getOperatingSystemMXBean();
        memFisicaLibre = mxbean.getFreePhysicalMemorySize();
        memFisicaTotal = mxbean.getTotalPhysicalMemorySize();
        memVirtualTotal = mxbean.getTotalSwapSpaceSize();
        memVirtualLibre = mxbean.getFreeSwapSpaceSize();     
    }

}