SafeChildren Banner

Havoc Oracle Solaris Experts

lunes, 30 de noviembre de 2009

Cálculo de Rendimiento de Apache 1.3.41 64bits vs 1.3.41 32bits en Solaris 10

Introducción
Continuando con la serie de Optimización de Páginas Web en Solaris, en esta ocasión vamos a ver qué diferencias de rendimiento podemos tener con la versión compilada de Apache 1.3.41 en 64bits y en 32bits, para ello continuaremos desde el punto anterior de Compilación de Apache 1.3.41 64bits en Solaris

Para ello, vamos a configurar solo el valor de la propiedad <Listen> del archivo de configuración $APACHE_HOME/conf/httpd.conf

Definición de las métricas de la prueba
Para realizar la prueba de rendimiento se han utilizado tres versiones de Apache HTTP 1.3.41 en Solaris x86_64 sobre una máquina virtual en MacOS X. Los detalles de la configuración son los siguientes:
  • Host: Virtual Box 3.0.10 r54097 Sobre MacOS X
  • Guest:  Solaris 10 10/09 s10x_u8wos_08a X86
  • Memoria: 2048 Megabytes
  • Versión Apache: Apache 1.3.41
Opciones de Compilación de Apache
He realizado tres compilaciones, dos en 32 bits y una en 64bits con los siguientes parámetros:
  • 32bits sin Opciones:
./configure \
"--with-layout=Apache" \
"--enable-module=rewrite" \
"--enable-module=expires" \
"--enable-module=headers" \
"--enable-module=mmap_static" \
"--enable-module=rewrite" \
"--add-module=src/modules/extra/mod_bandwidth.c" \
"--permute-module=BEGIN:bandwidth" \
"--activate-module=src/modules/extra/mod_security" \
"--enable-module=security" \
"--disable-module=status" \
"--enable-module=so" \
"--prefix=/opt/www/32/apache-1.3.41" \
"$@"
  • 32bits Configure con CFLAGS="-O2"
CFLAGS="-O2" \
./configure \
"--with-layout=Apache" \
"--enable-module=rewrite" \
"--enable-module=expires" \
"--enable-module=headers" \
"--enable-module=mmap_static" \
"--enable-module=rewrite" \
"--add-module=src/modules/extra/mod_bandwidth.c" \
"--permute-module=BEGIN:bandwidth" \
"--activate-module=src/modules/extra/mod_security" \
"--enable-module=security" \
"--disable-module=status" \
"--enable-module=so" \
"--prefix=/opt/www/32/apache-1.3.41" \
"$@"
  • 64bits Configure con CFLAGS="-m64 -O2"
CFLAGS="-O2 -m64" \
./configure \
"--with-layout=Apache" \
"--enable-module=rewrite" \
"--enable-module=expires" \
"--enable-module=headers" \
"--enable-module=mmap_static" \
"--enable-module=rewrite" \
"--add-module=src/modules/extra/mod_bandwidth.c" \
"--permute-module=BEGIN:bandwidth" \
"--activate-module=src/modules/extra/mod_security" \
"--enable-module=security" \
"--disable-module=status" \
"--enable-module=so" \
"--prefix=/opt/www/64/apache-1.3.41" \
"$@"
Herramientas de Testing
Se han utilizado las herramientas de Apache Benchmark, que se encuentra en $APACHE_HOME/bin/ab y Apache JMeter. Para hacer una prueba más realista se han realizodo tres métricas con Apache Benchmark (una detrás de otra), y se ha calculado la media con los datos de conexión, rendimiento, etc. La definición de los parámetros son los siguientes:
  • Apache Benchmark (32bits)
$ /opt/www/32/apache-1.3.41/bin/ab -n 10000 -c 15 http://localhost:8000/
  • Apache Benchmarck (64bits)
$ /opt/www/apache-1.3.41/bin/ab -n 10000 -c 15 http://localhost:8080/
  • Apache JMeter (32bits y 64bits)
Número de Hilos: 15
Contador del Bucle: 10000
Resultados Obtenidos
A continuación vamos a ver los gráficos de resultados de las pruebas de Apache Benchmark (recordar que se han realizado tres métricas y luego la media)

Apache 1.3.41 32bits sin Optimizaciones


Apache 1.3.41 32bits con Optimización -O2


Apache 1.3.41 64bits con Optimización -O2 -m64


Comparativa de las tres gráficas: 32 vs 32plus v2 64


Resultados de JMeter 32bits



Resultados de JMeter 64bits


Conclusiones
Aunque este test es bastante sencillo, podemos ver como la compilación en 64bits de Apache nos proporciona un mayor rendimiento, además, con el simple hecho de incluir <-O2> ya obtenemos una mejoría con la configuración por defecto.

Esto, que a simple vista es obvio, puede hacernos ver la importancia de compilar nuestros aplicativos en la arquitectura en la que queramos ejecutarlo, y en la medida de lo posible, evitar los paquetes precompilados para los entornos de producción.

En la siguiente entrega, veremos cómo podemos ir configurando Apache HTTP Server para obtener mayor rendimiento utilizando mod_expires y mod_gzip.

Referencias

viernes, 27 de noviembre de 2009

Compilar Apache 1.3.x Solaris 64bit con mod_bandwidth y mod_security

Introducción
Vamos a ver cómo podemos compilar la versión 1.3.41 de Apache HTTP Server en Solaris 10 en 64bits. La compilación en 64bits no es muy diferente de la de 32bits, realmente es introducir el modifcador -m64 en los flags de CC, sin embargo, si utilizamos módulos adicionales como(mod_bandwidth, mod_security, etc.  debemos incluir las bibliotecas de 64bits de /usr/sfw en nuestro LD_LIBRARY_PATH_64

Si recordais la Instalación de MemCached en 64bits sobre Solaris, también teníamos que adaptar las variables de LD_LIBRARY_PATH, tanto la de 32bits como la de 64bits, en la instalación de Apache HTTP Server ocurre lo mismo.

Módulos Adicionales
En esta ocasión vamos a instalar dos módulos adicionales dentro del core del servidor Apache
  • mod_bandwidth, nos permite establecer usos de ancho de banda por dominio, ip, usuario
  • mod_security, firewall capa 7 (Firewall de aplicación)
Además, vamos a habilitar los módulos de rewrite, headers, expires y so, este último para poder compilar el módulo jk que nos permite unir Apache HTTP Server con Apache Tomcat

Instalación de Módulos Adicionales
Para que podamos instalar los módulos dentro del core debemos copiar los mod_XXX.c al directorio $APACHE_HOME/src/modules/extra y de esta forma, podemos activarlos en la configuración.

Descargamos el source de Apache HTTP Server 1.3 y lo descomprimimos en $HOME/Apache
$ mkdir ~/Apache
$ cd  ~/Apache
$ wget http://apache.rediris.es/httpd/apache_1.3.41.tar.gz
$ gtar zxpf apache_1.3.41.tar.gz
Hay que tener en cuenta que la versión de mod_security para Apache HTTP Server 1.3.x es la 1.9.5, a partir de esta versión, son sólo para Apache HTTP Server 2.x, (aqui tienes un acceso director ala descarga de mod_security)
$ wget http://downloads.sourceforge.net/project/mod-security/modsecurity-apache/1.9.5/modsecurity-apache_1.9.5.tar.gz?use_mirror=ovh
$ gtar zxpf modsecurity-apache_1.9.5.tar.gz
$ cd modsecurity-apache_1.9.5/apache1/
$ cp mod_security.c ~/Apache/apache_1.3.41/src/modules/extra/
Descargar e Instalar mod_bandwidth
$ wget ftp://ftp.cohprog.com/pub/apache/module/1.3.0/mod_bandwidth.c
$ cp mod_bandwidth.c  ~/Apache/apache_1.3.41/src/modules/extra/
Compilación de Apache
Una vez preparado el source de Apache, vamos a compilarlo utilizando los modificadores -m64 como hemos comentado al principio. Recordar que debemos establecer la variable LD_LIBRARY_PATH_64 para que nos encuentre las bibliotecas correctas.
$ export LD_LIBRARY_PATH_64=/lib/64:/usr/lib/64:/usr/sfw/lib/64:/usr/ccs/lib
$ CC="gcc" \
   CFLAGS="-O2 -m64" \
   ./configure \
      "--with-layout=Apache" \
      "--enable-module=rewrite" \
      "--enable-module=expires" \
      "--enable-module=headers" \
      "--enable-module=mmap_static" \
      "--add-module=src/modules/extra/mod_bandwidth.c" \
      "--permute-module=BEGIN:bandwidth" \
      "--activate-module=src/modules/extra/mod_security" \
      "--enable-module=security" \
      "--disable-module=status" \
      "--enable-module=so" \
      "--prefix=/opt/www/apache-1.3.41" \
     "$@"
Instalación y Verificación de la Instalación
Si todo ha compilado correctamente, podemos hacer una instalación y posteriormente la verificación con ldd, para instalar simplemente haremos
# make install
Y para verificar que todo está correcto
$ ldd /opt/www/apache-1.3.41/bin/httpd
        libsocket.so.1 =>        /lib/64/libsocket.so.1
        libnsl.so.1 =>   /lib/64/libnsl.so.1
        libpthread.so.1 =>       /lib/64/libpthread.so.1
        libexpat.so.1 =>         /usr/sfw/lib/64/libexpat.so.1
        libc.so.1 =>     /lib/64/libc.so.1
        libmp.so.2 =>    /lib/64/libmp.so.2
        libmd.so.1 =>    /lib/64/libmd.so.1
        libscf.so.1 =>   /lib/64/libscf.so.1
        libdoor.so.1 =>  /lib/64/libdoor.so.1
        libuutil.so.1 =>         /lib/64/libuutil.so.1
        libgen.so.1 =>   /lib/64/libgen.so.1
        libm.so.2 =>     /lib/64/libm.so.2
Si no establecemos el LD_LIBRARY_PATH_64 el resultado será que intentará enlazar con la versión de 32bits de libexpat.so.1
# ldd /opt/www/apache-1.3.41/bin/httpd
        libsocket.so.1 =>        /lib/64/libsocket.so.1
        libnsl.so.1 =>   /lib/64/libnsl.so.1
        libpthread.so.1 =>       /lib/64/libpthread.so.1
        libexpat.so.1 =>         /usr/sfw/lib/libexpat.so.1 - clase ELF incorrecta: ELFCLASS32
        libc.so.1 =>     /lib/64/libc.so.1
        libmp.so.2 =>    /lib/64/libmp.so.2
        libmd.so.1 =>    /lib/64/libmd.so.1
        libscf.so.1 =>   /lib/64/libscf.so.1
        libdoor.so.1 =>  /lib/64/libdoor.so.1
        libuutil.so.1 =>         /lib/64/libuutil.so.1
        libgen.so.1 =>   /lib/64/libgen.so.1
        libm.so.2 =>     /lib/64/libm.so.2
Editar la Configuración del Servidor
Una vez tengamos nuestro servidor instalado y verificado, podemos comenzar a configurarlo.

Conclusiones
Hemos visto cómo instalar la versión de 64bits de Solaris con los módulos mod_security y mod_bandwidth que nos permiten establecer un Firewall de Capa 7 y un control de la tasa de transferencia.

Con estos módulos cargamos, podemos comenzar con la configuración de nuestro servidor Apache que utilizaremos en los ejemplos de Optimización de Aplicativos Web en Solaris.

En la siguiente entrega, comenzaremos con los parámetros de configuración del archivo $APACHE_HOME/conf/httpd.conf


Referencias

jueves, 26 de noviembre de 2009

Eliminar Unknown hostname Solaris 10

Introducción
Hace un tiempo explicaba cómo Eliminar "Unknown Hostname" pero en Solaris 9, bien, ahora toca el turno de Solaris 10

En Solaris 10, simplemente debemos establecer el valor de /etc/nodename y Solaris se encargará de asignar ese valor a nuestro Host.
# echo "zooey" > /etc/nodename
Una vez rebotado el sistema, veremos como en el archivo /etc/hosts existe una nueva entrada con el comentario de Added by DHCP, en mi caso zooey
# cat /etc/hosts
  #
  # Internet host table
  #
  ::1     localhost      
  127.0.0.1       localhost      
  10.0.2.15      zooey    # Added by DHCP

Conclusiones
Esta vez, en Solaris 10 todo es mucho más sencillo y rápido, aunque siempre puedes utilizar el antiguo método si quieres ...


Referencias

martes, 24 de noviembre de 2009

Cálculo de Rendimiento utilizando Apache JMeter - Parte 1

Instalación
En este primer post vamos a ver cómo utilizar JMeter para establecer un "Base Time Line" para nuestros cambios de configuración.

Apache JMeter es un aplicativo diseñado para obtener métricas de rendimiento de una forma automática y repetible. Ésto que parece no es muy importante, sí que lo es. Una de las cosas que debemos eliminar de nuestro vocabulario cuando empecemos a realizar pruebas de carga son: "parece que, más rápido, más lento, ..." todas estas expresiones no nos sirven ya que dependen de muchos factores, aunque el mayor problema es que son subjetivas y dependientes de una/varias personas.

JMeter nos ofrece datos "la página tarda 2,7 seg" ya no depende de si es "rápido" o "lento" son "2,7 seg", si hacemos un cambio y JMeter ofrece "2,9 seg", el cambio hace que el sistema responda más lento.

Debemos tener en cuenta que JMeter no es un navegador y por lo tanto, no va a procesar los código JavaScript, me explico, JMeter no va a procesar los document.write del código HTML. Por ejemplo, el siguiente bloque de código no será interpretado por JMeter y por lo tanto, las latencias de render no se computarán.
<script type='text/javascript'>new BannerManager('http://openads.test.com/').getBanner(106,'banner106',true,-1,false,'null');script>
<script type='text/javascript'>new BannerManager('http://openads.test.com/').getBanner(107,'banner107',true,-1,false,'null');script>
  
<script type="text/javascript">
     var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
     document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
script>
Una vez aclarado el funcionamiento de JMeter, vamos a ver cómo configurar una batería de pruebas para simular el acceso a nuestras webs.

Instalación de JMeter
JMeter es una aplicación Java y necesita de JVM 1.5+ para poder ejecutarse. La instalación simplemente es descomprimir el archivo tar.gz en la ubicación que nosotros queramos ($JMETER_HOME)

Lanzar JMeter
Antes de lanzar JMeter vamos a analizar si las pruebas que vamos a llevar a cabo van a ser muy complejas, ya que si así fuera, necesitaremos ampliar la memoria asignada por defecto a JMeter.

JMeter se inicia con un tamaño máximo de memoria de 512Mb, y aunque en la mayoría de los casos es suficiente, yo suelo configurarlo para que abra con 1024Mb.

Para modificar el parámetro de memoria, simplemente incluiremos una variable de entorno llamada JVM_ARGS donde se le asignan los parámetros de la máquina virtual, por ejemplo
$ export JVM_ARGS="-server -Xms1024m -Xmx1024m"
$ jmeter.sh
También podemos editaremos el archivo $JMETER_HOME/bin/jmeter y cambiar el valor de HEAP para asignarle los valores que deseemos, en mi caso 1024m
# This is the base heap size -- you may increase or decrease it to fit your
# system's memory availablity:
HEAP="-Xms1024m -Xmx1024m"
Una vez configurado nuestro JMeter, ejecutaremos el script de arranque $JMETER_HOME/bin/jmeter.sh y se nos mostrará nuestro entorno de trabajo que se ve a continuación



Como podemos observar, JMeter nos ofrece dos categorías dentro del árbol principal
  • Plan de Pruebas
  • Banco de Trabajo
En esta primera parte, vamos a ver cómo configurar un nuevo plan de pruebas, y en la segunda parte veremos cómo podemos utilizar el Banco de Trabajo


Nota: En JMeter no existe el botón Guardar y por lo tanto, cuando hagamos un "Focus Lost" del componente éste quedará guardado.

Configurar un Nuevo Plan de Pruebas
Lo primero que debemos hacer es añadir un Grupo de Hilos, para ello seleccionaremos Plan de Pruebas y haciendo click con el botón derecho Añadir->Grupo de Hilos. Esto representará a nuestros usuarios, es decir, si queremos comprobar cómo responde nuestro aplicativo con 50 usuarios concurrentes, en la propiedad Número de Hilos deberemos poner 50.

Para establecer un Base Time Line debemos establecer el valor de Número de Hilos a 1, y Contador del Bucle a un valor superior a 1, de esta forma, podemos obtener la media de ejecución con un sólo usuario y, de esta forma, tomaremos este dato como nuestro punto de partida.
Cuanto mayor sea el valor de Contador del Bucle mejor será la precisión, ya que obtendremos más muestras y por lo tanto la media será más realista.

Ahora seleccionaremos nuestro Grupo de Hilos y con el botón derecho Añadir->Elementos de Configuración->Valores por Defecto para Petición HTTP. Esto nos permitirá incluir los valores generales de la petición como: Nombre del Servidor, Puerto, Protocolo y Encoding.

 Seleccionamos Grupo de Hilos y con el botón derecho Añadir->Muestreador->Petición HTTP y, como hemos introducido Valores por Defecto simplemente deberemos editar el valor de la propiedad Path.

Por último, introduciremos un Listener que nos proporcionará los valores de la muestra, en este primer ejemplo vamos a introducir un Árbol de Resultados, para ello, seleccionaremos Grupo de Hilos y botón derecho Añadir->Listener->Ver Árbol de Resultados

Ya sólo nos queda guardar la prueba, Archivo->Guardar Como ... y podemos ejecutarla utilizando el menú Lanzar->Arrancar y ver el resultado en Ver Árbol de Resultados.

Como podéis ver, el funcionamiento de JMeter es sencillo y la creación de planes de pruebas no es muy complicado, en cuatro clicks hemos obtenido un plan de pruebas, sin embargo la información que obtenemos con este Sencillo Plan no nos aporta mucho, vamos a ver cómo hacer un plan más realista. Podéis descargar esta prueba sencilla de JMeter HTTP

Instalar nuevo Listener

Antes de comenzar con el plan de pruebas vamos a instalar un Listener que nos mostrará de forma gráfica, y más amena, el rendimiento y tiempo de respuesta de nuestro muestreador. Para ello, debemos descargar e instalar Better JMeter Graphs, después reiniciaremos el JMeter. Una vez hecho esto, tendremos un nuevo Listener llamado Statistical Aggregate Report

Configurar un Plan de Pruebas Más "Complicado"
Al igual que hemos hecho en la Prueba Sencilla de JMeter para HTTP añadiremos un Grupo de Hilos, añadiremos también Valores por Defecto para Petición HTTP, ahora viene algún cambio, seleccionamos Grupo de Hilos y con el botón derecho Añadir->Elemento de Configuración->Gestor de Cookies HTTP.

Los usuarios no hacen siempre las mismas iteraciones, es decir, Home->Pagina1->Pagina2->Home, y por lo tanto, si queremos hacer un plan de prueba que pueda simular  a un usuario, debemos tener en cuenta esto, por ello, JMeter nos ofrece el Controlador Lógico Random Order, así que seleccionamos Grupo de Hilos y con el botón derecho del ratón Añadir->Controlador Lógico->Random Order.

Ahora vamos a introducir los muestreadores HTTP dentro de nuestro controlador lógico, para ello, seleccionamos Controlador Random Order y con botón derecho Añadir->Muestreador->Petición HTTP y aquí pondremos la primera página. Deberemos repetir este proceso para todas las páginas que queremos muestrear.

Por último, vamos a añadir nuestro Listener seleccionando Grupo de Hilos y con el botón derecho Añadir->Listener->Statistical Aggregate Report, guardamos la prueba y ejecutamos. Podéis descargar la Prueba JMeter HTTP Multiples Páginas


Conclusión
En esta primera parte hemos visto cómo movernos con JMeter y las opciones que nos aporta, además, tenemos el resultado en formato gráfico al incluir el listener alternativo.

En la siguiente parte, veremos cómo podemos crear pruebas mucho más complejas y cómo establecer valores de control en los muestreadores

Referencias

domingo, 22 de noviembre de 2009

Optimización de Aplicaciones Web en Solaris

Introducción
En esta serie de post's vamos a ver cómo podemos exprimir al máximo nuestros servidores Solaris, y con el apoyo de los programadores hacer que el rendimiento de nuestras aplicaciones Web se vea mejorado.

Antes de comenzar, debemos hablar de las capas de optimización (tuning) que existen y la importancia de cada una.


Uno de los errores mas comunes es creer que cambiando el Hardware se conseguirá el mayor rendimiento, por ejemplo, si tenemos una CPU cargada, se pone más CPU (por ejemplo el doble, pasamos de 4 a 8 CPU) y se espera que el rendimiento aumente en relación al incremento de potencia, ERROR.

La capa HARDWARE es la que menos relación COSTE-RENDIMIENTO nos va a ofrecer, entonces por qué empezamos por el HARDWARE? Buena pregunta, la respuesta es muy sencilla: Es el cambio que menos trauma supone a los desarrolladores, y por lo tanto a los aplicativos. Si, es cierto, todos nos hemos encontrado en la situación de:

Como arquitecto le explicas:
  • "Necesito que cambies la aplicación X para que haga Z y reduzcas el número de llamadas a DB haciendo F"
Y la respuesta desde desarrollo es:
  • "Imposible, tenemos que tocar F,G,H, … mucho, mucho. Eso es problema de la máquina, el Software está súper optimizado"
Bien, vamos a ver cómo podemos enfrentarnos a estas situaciones y salir airoso de ellas siguiendo unas pautas y mejoras en nuestras arquitecturas.

En el primer post de la serie comenzaremos hablando de Cálculo de Rendimiento utilizando Apache JMeter y seguiremos con Parametrización de Apache para Cacheo de contenido, espero que os guste y mañana comenzaremos esta nueva serie.