Configuración y uso de Apache JServ
|
Ari Halberstadt, 1999 (ari@shore.net) Apache JServ es un módulo para el popular servidor web Apache que implementa la API de servlets de Java de Sun para ejecutar codigo del lado del servidor. Puede que esté interesado en este artículo si esta desarrollando software Java para ejecutarlo en un web site y se usa el servidor Apache. Actualmente el servidor Apache es el más popular y utilizado en Internet. Tanto el servidor Apache como el módulo Apache JServ son libres e incluyen su código fuente completo. Este artículo proporciona información sobre cómo usar Apache JServ para desarrollar servlets de Java, incluyendo tanto la instalación básica como configuración y gestión interemedia y avanzada. Este artículo (o una versión muy parecida) aparece en el libro Professional Java Server Programming, publicado por Wrox Press. Un artículo relacionado, centrado en la configuración de Apache Jserv desde la perspectiva de un administrador de Apache aparece en el libro Professional Apache de Peter Wainwright, también publicado por Wrox Press. Nota: Los ejemplos de este artículo han sido probados con Apache JServ 1.0b5, que fue la última release beta antes de la versión final 1.0 del 14 de Junio de 1999.
Contenido
ArquitecturaLos Java servlets deben ser ejecutados desde una máquina virtual Java (JVM de ahora en adelante), y por lo tanto cualquier entorno de ejecución de servlets debe incluir una. Añadir una JVM al servidor Apache no es una opción viable, la complejidad y sobrecarga asociadas a una JVM son prohibitivas, y degradarían la arquitectura del servidor. La solución adoptada con Apache JServ ha sido separar la JVM del servidor Apache. Esta separación proporciona, además, diversas ventajas. Permite el uso de cualquier JVM compatible proporcionada por cualquier proveedor. No se tiene que hacer ninguna modificación al servidor web cuando se hace un cambio en la JVM, como actualizarla a una versión mejorada. También proporciona mayor estabilidad el separar los procesos, permitiendo así protecciones de proceso y nivel por el sistema operativo. Si la JVM cae o se desconfigura, el servidor web seguira funcionando normalmente. También proporciona funcionalidades avanzadas, como arranque automático versus arranque manual, diferentes JVMs para diferentes configuraciones y la habilidad de soportar balance de carga en sites con un alto tráfico. El servidor Apache incorpora una arquitectura modular, mediante la que se le pueden añadir funcionalidades. Los módulos pueden ser enlazados con el servidor estáticamente o bien puden ser cargados de forma dinámica usando DSO (objectos dinámicos compartidos, Dinamic Shared Object) en Unix o DLL (Dynamically Linked Libraries) en Windows. La API para estos componentes modulares está basada en el lenguaje C. Apache JServ está implementado como dos componentes separados, uno escrito en C y el otro en Java, llamado Protocolo Apache Jserv (Apache JServ Protocol-AJP). La versión actual de este protocolo es la 1.1., por lo que le denomina ajpv11. El lado C de Apache JServ, llamado mod_jserv, proporciona una interficie entre el servidor web Apache y el lado Java. El módulo pasa peticiones e información entre el servidor web y el lado Java, y puede ser usado para arrancar y parar automáticamente la JVM en que el se ejecuta dicho lado Java. El lado Java de Apache JServ, llamado el Motor de Servets (Servlet Engine), implementa la API servlet, y es donde está la mayoría de las funcionalidades del Apache JServ. El lado Java está, de hecho, completamente separado del lado C, y el único enlace entre ellos es el AJP. Así, se puede atacar el lado Java desde cualquier servidor web siempre que se tenga un módulo apropiado de comunicación usando AJP para ese servidor web. El lado C, o mod_jserv,se puede entender como un cliente del lado Java del Apache JServ. Del mismo modo, el lado Java se puede entender como un servidor que acepta peticiones desde el cliente. Éste es, esencialmente, un modelo de tres capas, en el que el navegador actúa como front end, el servidor web es la capa media y el lado C del Apache JServ es el back end. Este modelo de tres capas se puede extender a uno de N capas si se accede a servicios adicionales como bases de datos o servidores de aplicaciones a través de Apache JServ. En este modelo, la capa comprendida por servidor web Apache y mod_jserve puede ser reemplazada con cualquier programa que use el protocolo AJP para comunicarse con Apache JServ. Apache JServ introduce también los conceptos de almacenes (repositories) y de zonas de servlets (servlet zones). Los almacenes de servlets son lugares desde donde son llamados los ficheros de clases de Java, incluyendo ficheros JAR (Java ARchives) y directorios que contengan jerarquias de clases de Java. Las zonas de servlets (servlet zones) son análogas a hosts virtuales en un servidor web. Cada zona puede tener su propio conjunto de servlets, e incluso usar una JVM dedicada. Secciones posteriores detallarán más cómo usar zonas de servlets y almacenes.
Instalación básicaEsta sección proporciona una introducción rápida para tener funcionando en una máquina una instalación de Apache y Apache JServ. Se pueden explorar opciones de configuración más avanzadas una vez se haya completado con éxito la instalación básica. Ésta consiste en dos pasos principales: instalación del servidor web Apache, y seguidamente la instalación del motor de servlets Apache Jserv. También se puede añadir Apache JServ a un servidor Apache ya existente saltando la instalación del servidor, haciendo sólo la instalación del Apache JServ. El ejemplo de instalación proporciona un punto de partida básico para explorar servlets Java usando Apache JServ, pero hay unos cuantos aspectos de una configuración completa que se pueden continuar explorando. Para trabajar con Apache JServ sacándole partido se deberían entender conceptos básicos, que incluyen los diferentes tipos de ficheros de configuración, las zonas de servlets, los almacenes (repositories) de clases, la rellamada automática de clases y cómo añadir servlets. Puede que también quieras explorar temas más avanzados, como mapeo de URLs a servlets, configuración de hosts virtuales, uso de múltiples JVMs, mejora del rendimiento, consideraciones sobre seguridad y funcionalidades añadidas.
RequerimientosSe necesita un sistema con JDK 1.1 o 1.2. También se necesita bajar e instalar el Java Servlet Development Kit (JSDK), versión 2.0, desde el website de Sun: http://java.sun.com/products/servlet/index.html. La versión 1.0 de Apache JServ es comptabile sólo con la versión 2.0 del JSDK, y no funcionará con ninguna otra versión de JSDK. Para la instalación en un sistema Unix también se necesita un compilador C y la utilidad make, como por ejemplo gcc y gmake del proyecto GNU, disponibles en el web site de Free Software Foundation www.fsf.org. Casi todos los sistems Unix incluyen versiones apropiadas o equivalentes a estos programas en su instalación estándar. Para la instalacion en Windows NT, corriendo sobre un i386 o compatible, no se necesita un compilador de C, ya que estan disponibles directamente los programas de instalación conteniendo los binarios compilados de Apache y Apache Jserv. Los requerimientos de disco son mínimos, una instalación completa de Apache y Apache JServ en mi sistema Linux (sobre Intel Pentium) ocupa alrededor de 3 MB, y necesita unos 10 MB adicionales para compilar y construir ambos programas. Los requerimientos de memoria dependen, en gran manera, del sistema operativo que se tenga y de la JVM. Como la JVM utilitza la parte del león de los recursos de memoria, se debe consultar la documentación de la JVM propia, aunque una buena aproximación es tener, al menos, 32 o 64 MB disponibles. Antes de instalar Apache JServ se debería verificar que se tiene una instalación de Java operativa. El intérprete debe ser compatible con JDK 1.1, lo que se puede comprobar con el comando java -version java version "1.1.7" Se puede comprobar si se puede compilar código Java simplemente compilando un programa de prueba. Per ejemplo, guardando el siguiento código en un fichero llamado HolaMundo.java: public class HolaMundo {
public static void main(String argv[])
{
System.out.println("Hola, mundo!");
}
}
y despues compilando y ejecutando el programa: javac HolaMundo.java java HolaMundo Hola, mundo! Si no se puede compilar y ejecutar este pograma, deberían consultarse las instrucciones de instalación del JDK. Para simplificar el desarrollo de servlets, se puede añadir el path del JSDK al classpath, lo que permite que scripts de ejemplo que vienen con Apache JServ puedan localizar automáticamente el JSDK, si no, se tendrá que especificar el path del JSDK cada vez un servlet se compile. Por ejemplo, en Unix, añadiendo las líneas CLASSPATH=$CLASSPATH:/usr/local/java/jsdk/lib/jsdk.jar export CLASSPATH al fichero .profile, en el que /usr/local/java/jsdk es el sitio donde se ha instalado el paquete JSDK de Sun. UnixHay que bajarse, descomprimir, configurar, compilar e instalar el servidor Apache y el motor de servlets Apache JServ. Cada producto incluye suficientes directivas/instrucciones para configurarlo, compilarlo e instalarlo en sus respectivos documentos INSTALL. La principal decisión a tomar es compilar Apache con DSO o bien enlazar (linkar) Apache JServ estáticamente con el servidor. El soporte DSO permite a Apache llamar módulos en tiempo de ejecución, reduciendo así el volumen del ejecutable y añadiendo y eliminando los modulos más convenientes, pero no todos los sistemas proveen soporte DSO, por lo que, en ese caso, se tiene que usar una compilación estática. Para tener una referencia, he incluido las instrucciones que usé para hacer una instalación limpia de Apache v1.3.6 y Apache JServ 1.0b5 en mi sistema Red Hat Linux v5.1. He incluido dos versiones de dos grupos de instrucciones: uno compilando Apache con soporte DSO, y otro enlazando las librerías estáticamente. Para otros sistemas, se necesita adaptar estos comandos, y también se debe instalar las versiones más recientes de Apache y Apache JServ. En estos ejemplos, yo he utilizado la utilidad wget (del proyecto GNU) para bajarme las aplicaciones, pero si no está en el sistema propio, se puede utilizar cualquier navegador para bajártelas. Necesitarás hacer la instalación como un usuario con suficientes privilegios como para escribir en los diferentes directorios, un usuario como por ejemplo root. Sin embargo, puedes instalar los programas en cualquier sitio de tu disco, incluso en tu directorio personal (home), ya que el directorio de instalación se indica usando la directiva --prefijo en el script de configuración de Apache, y con las directivas --with-apache-install o --with-apache-src en el caso del script de Apache JServ. ApacheScript de ejemplo para instalar el servidor web Apache con soporte DSO: % cd /usr/local/src % wget http://www.apache.org/dist/apache_1.3.9.tar.gz % gunzip -c apache_1.3.9.tar.gz | tar x % cd apache_1.3.9 % ./configure --prefix=/usr/local/apache --enable-module=most --enable-shared=max % make % make install Script de ejemplo para instalar el servidor web Apache sin soporte DSO: % cd /usr/local/src % wget http://www.apache.org/dist/apache_1.3.9.tar.gz % gunzip -c apache_1.3.9.tar.gz | tar x % cd apache_1.3.9 % ./configure --prefix=/usr/local/apache % make % make install Llegados aquí, y suponiendo que no ha habido errores durante la instalación, deberías poder arrancar Apache y confirmar que está trabajando accediento la página por defecto del mismo: % /usr/local/apache/bin/apachectl start % lynx http://localhost Si no puedes acceder a la página por defecto del servidor, entonces deberías mirar en el web site de Apache, http://www.apache.org, y en la documentación on-line para más asistencia. El procedimiento superior provee una instalación bastante rudimentaria, por lo que deberías refererirte a la documentación on-line de Apache, accesible a través de la página por defecto (http://localhost), para más instrucciones de configuración e instalación (por ejemplo, podrías activar el arranque automático de Apache después de cada rearranque del sistema). Apache JServScript de ejemplo para instalar Apache JServ con soporte DSO: % cd /usr/local/src % wget http://java.apache.org/jserv/dist/Apache_JServ_1.0.tar.gz % gunzip -c Apache_JServ_1.0.tar.gz | tar x % cd ApacheJServ_1.0 % ./configure --with-apache-install=/usr/local/apache % make % make install
Script de ejemplo para instalar Apache JServ como un módulo estáticamente enlazado (este script construye y reinstala Apache despue de construir e instalar Apache JServ): % cd /usr/local/src % wget http://java.apache.org/jserv/dist/Apache-JServ-1.0b5.tar.gz % gunzip -c Apache-JServ-1.0b5.tar.gz | tar x % cd ApacheJServ-1.0b5 % ./configure --with-apache-src=/usr/local/src/apache_1.3.9 --enable-apache-conf % make % make install % /usr/local/apache/bin/apachectl stop % cd /usr/local/src/apache_1.3.9 % make % make install Una vez instalado Apache JServ aún hay que configurar Apache para que se comunique con Apache JServ, lo que se puede hacer añadiendo la siguiente línea al final del fichero httpd.conf file (en /usr/local/apache/conf/httpd.conf): Include /usr/local/src/ApacheJServ-1.0b5/example/jserv.conf Asumiendo que la instalación haya procedido sin errores, deberías poder rearrancar Apache y acceder al servlet de ejemplo Hello, para confirmar que tu instalación haya sido correcta. /usr/local/apache/bin/apachectl restart (espera unos segundos para darle tiempo a Apache a rearrancar) lynx http://localhost/example/Hello Si no puedes acceder al servlet, entonces mira en la sección de solución de problemas. Prueba a acceder la URL unas cuantas veces, ya que puede ser que Apache JServ tarde algunos segundos en cargarse y empezar a aceptar peticiones. WindowsInstalar Apache consiste en bajarse y ejecutar el programa instalador y luego arrancar Apache. Se puede bajar el instalador para Windows desde http://www.apache.org/dist (para Apache 1.3.6 els instalador está en el fichero apache_1_3_6_win32.exe). Después de bajarte el fichero, ejecuta el instalador (haz doble click sobre el fichero .exe). Después de la instalación, arranca Apache desde el grupo de opciones de menú Apache Web Server, bajo el menú de Inicio desde el prompt de sistema (línea de comandos). Hecho esto, usa tu navegador para acceder a la home page por defecto en http://localhost. Si eso no funciona, consulta la documentación de Apache y el web site de Apache. Instalar Apache JServ consiste en bajarse y ejecutar el instalador, y luego rearrancar Apache. El instalador para Windows de Apache JServ está en http://java.apache.org/jserv/dist/. Para Apache JServ 1.0b5 el instalador está en el fichero Apache-JServ-1.0b5.exe. Después de bajarte el fichero, ejecuta el instalador (haz doble click sobre el fichero .exe), seleccionando la instalación integrada, de manera que Apache JServ será arrancado y parado automáticamente por el servidor web. Después de la instalación rearranca el servidor web (o sea, para y arranca el servidor). Para probar la instalación, accede a la URL http://localhost/servlets/IsItWorking, que debería ejecutar el servlet de ejemplo y mostrar una página simple. Si no puedes acceder al servlet, mira en la sección solución de problemas. Prueba a acceder la URL unas cuantas veces, ya que puede ser que Apache JServ tarde algunos segundos en cargarse y empezar a aceptar peticiones.
Ficheros de configuración y directivasApache y Apache JServ utilizan diversos ficheros de configuración. Respecto a Apache, el fichero más interesante es httpd.conf, donde estan (entre otras cosas) las directivas para la carga de módulos y la configuración del módulo mod_jserv. El fichero de configuración principal para el motor de servlets es el fichero de propiedades del motor, y suele ser jserv.properties. Contiene las propiedades pasadas a la JVM, opciones diversas y preferencias de seguridad, y una lista de todas las zonas de servlets y sus ficheros de propiedades respectivos. Cada zona de servlets usa también su propio fichero de propiedades, el fichero de propiedades de zona. Éste contiene propiedades que especifican almacenes (repositories) desde los que los servlets son llamados en la zona, si las clases son cargadas automaticamente cuando se cambian, y otros puntos especificos de cada zona de servlets Directivas de ApacheSi has instalado la configuración de Apache JServ, entonces habrás añadido una directiva Include en httpd.conf para añadir el fichero de configuración de ejemplo (estas directivas se usan para configurar mod_jserv de manera que se pueda comunicar con el motor de servlets). También puedes configurar mod_jserv añadiendo las directivas apropiadas en httpd.conf. Si estás usando Apache JServ como un módulo DSO, entonces deberías incluir una directiva LoadModule en httpd.conf para cargar mod_jserv. En Unix, esto se hace más o menos como sigue: LoadModule jserv_module libexec/mod_jserv.so En Windows, esto sería: LoadModule jserv_module modules/ApacheModuleJServ.dll La directiva LoadModule es parte de mod_so, y no deberías utilitzarla si has enlazado mod_jserv estaticament a Apache. Las directivas que son especificas de mod_jserv estan mejor puestas dentro de una directiva IfModule, de manera que el servidor web pueda arrancar incluso si mod_jserv se elimina de manera temporal. Por ejemplo, una instalación básica podría incluir las siguientes directivas en httpd.conf: <IfModule mod_jserv.c> ApJServProperties /usr/local/apache/conf/jserv.properties ApJServLogFile /usr/local/apache/logs/mod_jserv.log ApJServSecretKey DISABLED ApJServMount /servlets /servlets <Location /status/jserv/> SetHandler jserv-status order deny,allow deny from all allow from localhost </Location> </IfModule> Los comentarios en el fichero de configuración de ejemplo incluido en Apache JServ (bajo el directorio examples/jserv.conf) incluyen una descripción de todas las directivas de configuración disponibles. Actualmente este fichero se incluye en httpd.conf (a través de la directiva Include de Apache), después de una correcta instalación de Apache JServ. El fichero httpd.conf se carga sólo cuando el servidor web arranca, de manera que tendrás que rearrancar el servidor después de cualquier modificación. Propiedades del motorEl fichero de propiedades del motor es leído tanto por mod_jserv como por el propio motor de servlets. Este fichero contiene pares de propiedades nombre/valor. Un fichero de ejemplo, que contiene comentarios explicando cada propiedad, se incluye con la distribución de código de Apache JServ en examples/jserv.properties. Hay un fichero de propiedades distinto para cada JVM usada por Apache JServ. Este fichero contiene propiedades que se necesitan para lanzar la JVM, questiones de de seguridad y comunicación para comunicación con el servidor web Apache, y propiedades para activar rastreo (logging). Este fichero se llama sólo una vez en el arranque, por lo que cualquier cambio sólo será efectivo a partir de la reinicialización del servidor web y la JVM. A continuación hay un ejemplo de un fichero de configuración mínimo de un motor: wrapper.bin=/usr/local/java/jdk/bin/java wrapper.class=org.apache.jserv.JServ wrapper.classpath=/usr/local/jserv/lib/ApacheJServ.jar wrapper.classpath=/usr/local/java/jsdk/lib/jsdk.jar port=8007 security.allowedAddresses=127.0.0.1 security.authentication=false zones=servlets servlets.properties=/usr/local/apache/conf/servlets.properties En este ejemplo, las propiedades wrapper son usadas por mod_jserv para arrancar automáticamente el motor de servlets. La propiedad port indica qué puerto debe usar el motor para comunicarse con mod_jserv, y la propiedad zones lista las zonas de servlets a las que se puede acceder. La propiedad que empieza conel nombre de una zona de servlets, seguida por el texto ".properties" (en el ejemplo, servlets.properties) especifica la localización del fichero de propiedades de zona para cada zona de servlets. Propiedades de zonaCada zona de servlets usa un fichero de propiedades de zona. Este fichero contiene una lista de almacenes (repositories) que contienen ficheros de clase y servlets Java. También contiene alias y arguments de inicialización para los servlets de cada zona. A continuación hay un ejemplo de un fichero de configuración mínimo de propiedades de una zona. repositories=/usr/local/apache/servlets Este fichero de propiedades sólo indica un directorio que puede contener servlets.
Añadir y ejecutar ServletsLos servlets se añaden a una zona de servlets poniendo los ficheros compilados de la clase (.class) en uno de los almacenes de la zona. Por ejemplo, se puede añadir un serlvet a la zona de ejemplo de servlets que viene con la instalacin de Apache JServ poniendo el servlet compilado (.class) en el directorio de ejemplo, que esta en la carpeta exampe en la distribución fuente (p.e., /usr/local/src/ApacheJServ-1.0b5/example). Un buen servlet de ejemplo es SnoopServlet, que se incluye con el JSDK de Sun. Este servlet imprime la mayoría de la información que el motor de servlets le pasa al servlet. Puedes compilar SnoopServlet, lo que da una fichero llamado SnoopServlet.class, que luego tendrá que copiar al almacen de tu zona de servlets. Si estas usando la zona de servlets de ejemplo, deberías copiar el fichero de la clase compilada a /usr/local/src/ApacheJServ-1.0b5/example. Para ejecutar SnoopServlet, entra su URL en tu navegador: http://dominio:puerto/example/SnoopServlet Donde dominio es el nombre de tu dominio y puerto es el puerto por el que se accede a tu servidor web (usualmente es el 80). La forma general de acceder a un servlet es protocolo://host:puerto/zona/nombre Donde protocolo es usualmente http, host es la dirección IP o el nombre de tu servidor, puerto es el puerto para conectar al servidor, zona es el punto de montaje de una zona de servlets, y nombre es el nombre completo del servlet o un alias en la zona especificada. Un error común entre los que empiezan es intentar acceder a un servlet a través del AJP. AJP es sólo para comunicación interna entre el servidor web y Apache JServ, nunca se usa para acceder al servidor web. Así, no pruebes un URL como ajpv11://tudominio:8007/example/SnoopServlet, ya que no funcionará. Accede siempre a tus servlets usando un protocolo estándar como HTTP. Los servlets cuyas clases estan en un package se acceden a través de su nombre completo de clase. Por ejemplo, si añades un servlet llamado FooServlet en el paquete com.dominio.foo a una zona de servlets cuyo punto de montaje es /servlets, entonces deberías acceder a ese servlet mediante la URL http://dominio.com/servlets/com.dominio.foo.FooServlet Puedes ocultar el nombre del servlet y el paquete en la URL definiendo un alias para tu servlet. Esta definición del alias dentro de un almacén de servlets se hace mediante la propiedad servlet.name.code, donde name es el alias que quieres assiganr a tu servlet. Por ejemplo, para definir un alias foo para la clase com.dominio.foo.FooServlet, tienes que añadir la siguiente propiedad al fichero de propiedades de la zona: servlet.foo.code=com.dominio.foo.FooServlet Y para acceder al servlet hay que usar el URL http://dominio.com/servlets/foo Algunos servlets pueden necesitar información adicional, que se les pasa en el momento del arranque. Se puede pasar cualquier numero de argumentos a un servlet usando las propiedades initArgs en el fichero de propiedades de la zona, y se puede acceder a los argumentos usando el método getInitParameter de javax.servlet.ServletConfig. Por ejemplo, para pasar argumentos de inicialización a FooServlet, servlet.foo.initArgs=name=This is foo servlet servlet.foo.initArgs=purpose=Nothing in particular El formato de esta directiva es servlet.nombre.initArgs, donde nombre puede ser o bien un alias de un servlet o bien el nombre completo de la clase del servlet. Si tienes demasiados argumentos de inicialización para un servlet, quizás querrás guardarlos en un fichero separado. Esto puedes hacerlo omitiendo cualquier directiva initArgs en el fichero de propiedades de la zona y proporcionando, en cambio, un fichero <nombre>.initArgs en el mismo directorio que contiene la clase del servlet. La propiedad especial servlets.default.initArgs permite definir argumentos de inicialización que se pasan a todos los servlets. Por ejemplo, le puedes pasar la dirección e-mail de tu webmaster a todos tus servlets, de manera que incluyan la dirección en los mensajes de error generados por ellos. Normalmente, los serlvets son cargados en la memoria la primera vez que son llamados, de manera que si nadie llama nunca (accede) a un servlet, éste nunca será cargado en la memoria. Sin embargo, podrías querer que determinados servlets se ejecutaran cuando el servidor web (o la JVM) se arrancara. Para esto se usa la directiva servlets.startup, a la que se le proporciona una lista de servlets que seran ejecutados cuando la JVM se arranque. Se pueden añadir servlets a la lista s tienes servlets que hagan procesos en backgroundm, o servlets que tardan algunos segundos en arrancar y no quieres que tus usuarios tengan que esperar un retraso mínimamente notable.
Rutas (path) y rellamada de clasesLa ruta de clases es donde la JVM busca las definiciones de clases. La ruta de clases en Apache JServ se divide en una ruta de clases de sistema y en un conjunto de rutas de clases de zonas de servlets. La ruta de clases de sistema está compartida entre todos los servlets, mientras que la ruta de clases de las zonas de servlets es accesible sólo desde cada zona. La ruta de clases de sistema se define de dos maneras: de modo automática, usando la directiva wrapper.classpath en el fichero de propiedades del motor, o de modo manual, donde es cualquier cosa que se le pase al runtime de Java mediante la variable de entorno CLASSPATH o la opcion -classpath. Cada zona de servlets tiene asignado su propio cargador de clases. Éste es responsable de cargar las definiciones de clase desde los almacenes a la JVM y de detectar modificaciones en los almacenes de clases. Así, si tenemos dos zonas, A y B, y cada una de ellas usa la clase C del almacén R, entonces tendremos dos copias de la clase C, cada una de las cuales es inaccesible a la otra. De la misma manera, cualquier objeto que sea una instancia de la clase C será inaccesible a otras zonas. No importa que el almacén sea el mismo fichero o el mismo directorio, ya que cada uno tiene se cargador separado. Una característica útil para desarrollar servlets es la habilidad para rellamar clases automáticamente cuando se modifican. Apache JServ recargará las clases si un almacen que contiene una de ellas ha sido modificado, y una zona de servlets también será recargada si su fichero de propiedades se modifica; esto permite instalar y probar nuevas versiones de servlets sin tener que rearrancar el servidor. Las clases de la lista de una zona de servlets sólo son accesibles a esa zona. Además, sólo las clases cargadas desde un almacén de zona están sujetas a recarga automática si el almacén de zona o el fichero de propiedades cambian. Esto permite poner las clases más usadas y/o las más estables en la ruta de clase del sistema, dando así acceso a clases compartidas y mejorando el rendimiento en general. Por ejemplo, las clases del JDK y del JSDK deberían ponerse en la ruta de clase del sistema (CLASSPATH,-classpath). Así, una libreria estable y comunmente usada, como un driver JDBC, podría ponerse en la ruta de clases del sistema. La rellamada automática de clases reduce el rendimiento porque se debe comprobar cada almacén en cada una de las ejecuciones de un servlet. La rellamada está activada por defecto, pero se puede desactivar para una zona particular poniendo la propiedad autoreload en el fichero de propiedades de la zona como falsa (false). Esto puede conducir a una mejora significativa del rendimiento, a costa de un ciclo de desarrollo más pesado, ya que se requeriría entonces rearrancar el servidor cada vez que se modifica una classe. Otro problema de rendimiento de la rellamada de clases es que incluso un pequeño cambio en una clase forzará a una recarga de toda la zona. Esto no suele ser un problema si solo hay unas pocas clases, pero puede ser un problema de rendimiento significativo si hay varios almacenes grandes. Esto se puede esquivar moviendo los almacenes grandes a la ruta de clases del sistema; aunque se perderán los beneficios de la rellamada automática de clases para estos almacenes, se ganará la ventaja un cicle de actualización y pruebas más rápido en las clases con las que se trabaja. Cuando una zona de servlets se recarga, todos los objetos creados en la zona son destruidos. Con la recarga automàtica activada, incluso el más pequeño cambio en el fichero de propiedades de zona o de uno de los almacenes en una zona causarán la recarga de esa zona, lo que puede ser un problema si se mantienen los estados entre las ejecuciones de un servlet. Por ejemplo, si se mantiene una sesión de un usuario en memoria, se perderá cuando la zona sea recargada. En este caso, la recarga automática no es más que un caso especial del problema, más general, de mantener un estado persistente en un servlet. La mejor solución para mentener los datos de una sesión es proporcionar un mecanismo persistente: antes que Apache JServ destruya una zona de servlets, llama al método destroy() de cada servlet. Los servlets pueden, entonces, guardar los datos en un almacén persistente, como un fichero o una base de datos. Cuando los servlets son rellamados, sus métodos init() pueden leer la información guardada de la sesión. También se pueden guardar las sesiones siempre que se actualizen, previniendo así pérdidas de datos debidas a errores inesperados (e imprevisibiles, muchas veces: Caída de la JVM, fallos de tensión, etc.) El acceso a métodos implementados via Java Native Interface (JNI) debe ser provisto por las clases a través del cargador de clases de sistema en la ruta de clases de sistema. Esto es una limitación impuesta por la manera en que los cargadores de clases de Java están implementados, que sólo permiten al llamador de clases del sistema cargar métodos JNI. Dicho de otra manera, no se puede acceder a métodos JNI en clases llamadas a través de la ruta de clases de una zona de servlets, pero se pueden listar esas clases en la ruta de clase del sistema...
Añadir zonas de servletsApache JServ ejecuta todos los servlets en zonas de servlets, y puede ser configrado con una o más zonas de servlets. A cada zona se le asigna un único punto de montaje y un nombre. El punto de montaje corresponde a una prefijo URL único, de manera que todos los URL que empiezen por ese prefijo (por ese punto de montaje) serán manejados por un servlet de la zona especificada. Por ejemplo, la instalación por defecto incluye una sola zona llamada example, los URL cuyo path empiece con /example seran manejados por el servlet de la zona example. El disponer de múltiples zonas de servlets proporciona diversas ventajas: las zonas permitan separar servlets por criteros de seguridad, para ejecutar múltiples JVMs, para soporte de de múltiples hosts virtuales, etc. Cada zona de servlets requiere una directiva ApJServMount en el fichero httpd.conf de Apache, una entrada en el fichero de propiedades del motor (compartido) y un fichero de propiedades propio de la zona. La directiva ApJServMount indica a mod_jserv cómo mapear URLs a zonas de servlets. La sintaxis de la directiva es ApJServMount ruta protocolo://host:puerto/zona Donde ruta es la parte principal del URL que se mapea a la zona, protocolo el protocolo de comunicación interno AJP, host es la direción IP o el nombre del host en el que se ejecuta la JVM, puerto es el puerto por el que se comunicará internamente con Apache JServ, y zona es el nombre de una zona de servlets. Ruta y zona són obligatorios. Si se omite protocolo, se entenderá por defecto el valor de la directiva ApJServDefaultProtocol o ajpv11 en Apache JServv1.0. Si se omite host, se entenderá por defecto el valor de la directiva ApJServDefaultHost o el localhost de defecto. Y si se omite puerto, se entenderá por defecto el valor de la directiva ApJServDefaultPort o bien 8007. Por ejemplo, para mapear peticiones de la ruta /dev/servlets a la zona devservlets en la máquina local, se podría usar la directiva ApJServMount /dev/servlets /devservlets Las peticiones a cualquier URL que empieze por /dev/servlets serán manejadas por los servlets de la zona devservlets. En el fichero de propiedades del motor, habrá que añadir una entrada para la zona listandola en la propiedad zones y proporcionando la ruta al fichero de propiedades de la zona. Por ejemplo, zones=devservlets devservlets.properties=/usr/local/apache/conf/devservlets.pro perties El fichero de propiedades para la zona devservlets debe contener como mínimo una entrada repositories especificando un almacén del cual se llamarán los servlets, por ejemplo: repositories=/usr/local/apache/devservlets En este ejemplo, el almacén es un directorio en el cual se pueden poner servlets. Por supesto, hay que crear el diretorio: mkdir /usr/local/apache/devservlets Una vez se haya finalizado la configuración de la zona, hay que rearrancar el servidor web. Para el ejemplo superior, se puede usar una URL como http://tudominio/dev/servlets/MiServlet?address=foo@bar.com que ejecutará el servlet MiServlet en la zona devservlets.
Mapeo de URLsHay un par de maneras de mapear URLs, además de las zonas de servlets y los alias. El módulo mod_jserv puede mapear ficheros que acaben en un sufijo particular a un servlet de manera que, cuando el servlet se ejecuta, la ruta al fichero se pasa como información extra al servlet. La otra manera us usar el muy flexible módulo mod_rewrite, que se proporciona con Apache. La directiva ApJServAction el servlet que se ejecutará para ficheros que acaben en un sufijo determinado. La ruta al fichero solicitado se pasa al servlet, y éste puede acceder a ella mediante los métodos getPathInfo o getPathTranslated de javax.servlet.HttpServletRequest. Por ejemplo, el proyecto Java Apache proporciona el servlet Apache JSSI, que incluye la salida de otro servlet en un fichero HTML. Para mapear ficheros acabados en el sufijo .jhtml al servlet Apache JSSI, hay que añadir una línea como la siguiente en el fichero httpd.conf: ApJServAction .jhtml /servlets/org.apache.servlet.ssi.SSI Después de un rearranque del servidor, y asumiendo que el servlet Apache JSSI está instalado, cualquier fichero acabado en .jhtml será analizado por dicho servlet. Hay veces en que no se quiere que los usuarios vean una ruta como /dev/servlets/MiServlet al acceder al sitio. Alternativamente, también podría interesar 'envolver' ficheros existentes en un servlet para proporcionar autenticación o contenido dinámico. Apache incluye un módulo muy flexible, llamado mod_rewrite, que se puede usar para modificar URL de casi cualquier manera que pueda ocurrirse. Usar mod_rewrite con mod_jserv es como usar mod_rewrite con cualquier otor módulo o URL. Para los detalles, se debería consultar documentación y ejemplos proporcionados por el autor del módulo, Ralf S. Engelschall, que están incluidos en la distribución de Apache. Lo único importante que hay que recorder es que la directiva AddModule de mod_jserv debe estar antes de la directiva AddModule de mod_rewrite. Por ejemplo, en httpd.conf, ClearModuleList ... AddModule mod_jserv.c AddModule mod_rewrite.c Esto es así porque los módulos se ejecutan en la dirección inversa en que se especifican con la directiva AddModule, y mod_rewrite debe ejecutarse antes de mod_jserv. El resto de esta sección incluye algunos consejos simples para usar mod_rewrite con mod_jserv. El ejemplo siguiente reescribe cualquier URL que empiece por /auth con /servlets/AuthServlet. La opción [PT] indica a mod_rewrite que debe pasar la URL reescrite para procesos posteriores en Apache. <IfModule mod_rewrite.c> RewriteEngine on RewriteRule ^/auth(.*) /servlets/AuthServlet$1 [PT] </IfModule> Se puede decidir añadir contenido dinámico a una páginas estáticas añadiendo, por ejemplo, el servlet Apache JSSI, que proporciona funcionalidades de server-side include a los servlets Java. Asumiremos que se a añadido previamente una directiva ApJServAction de manera que los ficheros cuyo sufijo sea .jhtml iran a través del servlet Apache JSSI. Si se quiere obtener algún beneficio de esta nueva funcionalidad en los ficheros existentes, pero éstos no se pueden renombrar sin romper URLs ya existentes, y no se quiere mantener una lista de todos los mapeos de ficheros .html existentes a .jhtml, se puede usar la directiva RewriteMap de mod_rewrite y un pequeño programa en Perl para solucionar el problema: <IfModule mod_rewrite.c>
RewriteEngine on
RewriteMap suffixmap prg:/usr/local/apache/conf/suffixmap
RewriteRule ^(.*)\\.html% $1.${suffixmap:$1|html}
</IfModule>
Este ejemplo pasa cualquier URL acabado en .html al programa /usr/local/bin/suffixmap. El programa de mapeo de sufijos devuelve un nuevo sufjio o bien un string NULL para usar el sufijo por defecto. El código fuente del programa de mapeo de sufijos es: #!/usr/bin/perl
# Usado para el mapeo de urls con mod_rewrite
$| = 1;
$root = "/usr/local/apache/htdocs";
@suffixes = ("jhtml");
MATCH:
while (<>) {
chop;
$file = $root . $_;
foreach $suffix (@suffixes) {
if (-f "$file.$suffix") {
print "$suffix\\n";
next MATCH;
}
}
print "NULL\\n";
}
Este script concatena el directorio raiz de documentos del servidor con la URL proporcionada, y luego comprueba la existencia de un fichero con uno de los sufijos buscados (se pueden añadir fácilmente sufijos adicionales). Si se encuentra una coincidencia, el script devuelve el sufijo de la coincidencia a mod_rewrite escribiendo en la salida estandar, y si no escribe NULL para indicar ue el sufijo por defecto es el que debe usarse. Esta solución no es la aproximación más eficiente, dado que requiere una búsqueda en todos y cada uno de los URLS que acaben en .html. Sería mejor generar manual o automáticamente un texto o un fichero DBM que mapeara URL específicos. Sin embargo, el script anterior es conveniente para usarlo durante el desarrollo y demuestra algunas de las capacidades y flexibilidad de mod_rewrite.
Hosts virtualesLos hosts virtuales son una acertada manera de hacer que un sólo servidor web pueda manejar peticiones para múltiples dominios. Cada host virtual puede tener configuraciones separadas de Apache JServ, mientras diferentes directivas compartidas pueden situarse fuera de la configuración de cualquier host virtual. Las directivas compartidas incluyen las directivas para las propiedades y los ficheros de log (registro) y la URL de estado. Otras directivas, como los puntos de montaje de los servlets y las zonas, se pueden especificar separadamente para cada host virtual. El ejemplo siguiente muestra una configuración de muestra para dos hosts virtuales, llamados vhost1 and vhost2. # directivas compartidas LoadModule jserv_module libexec/mod_jserv.so <IfModule mod_jserv.c> ApJServProperties /usr/local/apache/conf/jserv.properties ApJServLogFile /usr/local/apache/logs/mod_jserv_log ApJServSecretKey DISABLED <Location /status/jserv/> SetHandler jserv-status order deny,allow deny from all allow from localhost </Location> </IfModule> NameVirtualHost 192.168.1.1 # directivas para vhost1 <VirtualHost 192.168.1.1> ServerName vhost1.com DocumentRoot /usr/local/hosts/vhost1/htdocs <Directory /usr/local/hosts/vhost1/htdocs> order allow,deny allow from all </Directory> <IfModule mod_jserv.c> ApJServDefaultHost vhost1.com ApJServMount /servlets ajpv11://vhost1.com/vhost1 </IfModule> </VirtualHost> # directivas para vhost2 <VirtualHost 192.168.1.1> ServerName vhost2.com DocumentRoot /usr/local/hosts/vhost2/htdocs <Directory /usr/local/hosts/vhost2/htdocs> order allow,deny allow from all </Directory> <IfModule mod_jserv.c> ApJServDefaultHost vhost2.com ApJServMount /servlets ajpv11://vhost2.com/vhost2 </IfModule> </VirtualHost> Para este ejempo se ha usado una dirección IP sin sentido en la red. La directiva ApJServDefaultHost se necesita porque ambos hosts virtuales comparten la misma direccion IP, y permita a Apache JServ dirigir cada petición a la zona de servlets correcta. Se necesitará crear los directorios htdocs para cada host virtual, y también los directorios donde almacenar los servlets: mkdir -p /usr/local/hosts/vhost1/htdocs mkdir -p /usr/local/hosts/vhost2/htdocs mkdir -p /usr/local/hosts/vhost1/servlets mkdir -p /usr/local/hosts/vhost2/servlets El fichero de propiedades del motor debería contener propiedades tanto para vhost1 como para vhost2 y permitir el acceso desde la dirección IP del host virtual: wrapper.bin=/usr/local/java/jdk/bin/java wrapper.class=org.apache.jserv.JServ wrapper.classpath=/usr/local/jserv/lib/ApacheJServ.jar wrapper.classpath=/usr/local/java/jsdk/lib/jsdk.jar port=8007 security.allowedAddresses=192.168.1.1 security.authentication=false zones=vhost1,vhost2 vhost1.properties=/usr/local/apache/conf/vhost1.properties vhost2.properties=/usr/local/apache/conf/vhost2.properties Cada zona necesita también el correspondiente fichero de propiedades de la zona, vhost1.properties and vhost2.properties, que son como cualquier otro fichero de propiedades de zona. El fichero vhost1.properties podria ser como lo que sigue: repositories=/usr/local/hosts/vhost1/servlets Se pueden añadir almacenes e indicaciones como para cualquier otra zona de servlets. Y se tiene que crear un fichero similar para vhost2. A partir de la configuración anterior, peticiones de URLs como http://vhost1.com/servlets/... serán manejadas por la zona de servlets vhost1, mientras peticiones de URLs como http://vhost2.com/servlets/... lo serán por la zona de servlets vhost2. Con la directiva ApJServMountCopy se pueden hacer zonas de servlets compartidas, accesibles por cada host virtual. Se puede usar esta directiva para proporcionar un conjunto común de servlets básicos para cada host virtual. Permitiendo la copia del montaje, las zonas definidas fuera de cualquier sección del host virtual son automáticamente accesibles para cada host virtual. Si las siguientes directivas se añaden a la parte compartida de la configuración de ejemplo del host virtual, entonces tanto vhost1 como vhost2 tendrán acceso a la zona /share. ApJServMountCopy on ApJServMount /share/servlets /share También se necesitará añadir un fichero de propiedades de zona y una entrada en el fichero de propiedades del motor para la zona de servlets compartida (sólo hay que seguir el mismo procedimiento que para cualquier otra zona de servlets). Así, dado un servlet MailServlet en la zona share, URLs como http://vhost1.com/share/servlets/MailServlet y http://vhost2.com/share/servlets/MailServlet ejecutarían la misma instancia de MailServlet.
Ejecutar Apache JServApache JServ se puede usar de dos modos, automático y manual. El modo automático es el mas conveniente para ejecutarlo, ya que maneja el arranque y parada de la JVM. El modo automático es apropiado para instalaciones básicas que utilizan una única JVM. En el modo manual, se debe lanzar la JVM usando un programa externo, como un shell script o un fichero batch. El modo manual da un trabajo extra de configuración, pero permite utilizar cualquier número de JVMs para, por ejemplo, proporcionar aislamiento entre cliente o para dar equilibrar el balance de la carga o la tolerancia a errores. En el modo automático, el módulo mod_jserv lanza automáticamente la JVM. El módulo tambien monitoriza la JVM y la relanza si ésta finaliza inesperadamente. Cuando el servidor Apache se rearranca o se para, el módulo rearranca o para la JVM. Todo lo que se necesita para configurar el modo automática es usar el valor "off" en la directiva ApJServManual en httpd.conf y configurar adecuadamente las propiedades wrapper en el fichero de propiedades del motor. El modo manual se requiere, en cambio, si se quiere hacer uso de más de una JVM, por ejemplo, un ISP que proporciona hosting virtual a sus clientes querrá proporcionar a cada cliente una JVM propia para asegurarse que los datos y ejecutables de cada uno de ellos se separan de los del resto. En sitios con alto tráfico también se pueden usar las características de balance de carga añadidads en Apache JServ 1.0b5. En el modo manual hay que lanzar la JVM. Esto se puede hacer directamente desde la línea de comandos, usando un shell script o un batch script, desde un script ejecutado en el arranque del servidor, etc. A continuación hay un ejemplo de un shell script de Unix que se puede usar para lanzar Apache JServ en modo manual (antes de usar el script, habrá que ajustar las rutas (paths) para las localizaciones de los ficheros en el propio sistema). Shell script de Unix para lanzar Apache JServ en modo manual #!/bin/sh properties=/usr/local/apache/conf/jserv.properties log=/usr/local/apache/logs/jserv_manual.log CLASSPATH=$CLASSPATH:/usr/local/jsdk/lib/jsdk.jar CLASSPATH=$CLASSPATH:/usr/local/jserv/lib/ApacheJServ.jar java org.apache.jserv.JServ $properties $1 2>> $log Cuando se ejecuta en modo manual, el error estándar y la salida estándar de la JVM (System.err and System.out) van, por defecto, al dispositivo de salida regular, normalmente la ventana de terminal local. Se puede redireccionar la salida (ambas) a un fichero de log, de manera que el terminal no se llene de los datos de salida y además se podrá guardar para futuras referencias. Uno de los defectos del modo manual es que no hay una monitorización de la JVM establecida. Si la JVM falla, hay que rearrancarla manualmente. Un paquete de monitorización externo, como mon http://www.kernel.org/software/mon/, es entonces una necesidad para cualquier site que use modo manual Otro de los defectos del modo manual es que no se notifica a la JVM el rearranaque o parada del servidor web. Como regla, nunca se debería terminar un proceso Apache JServ usando el comano kill de Unix o el gestor de tareas de Windows NT. Cerrar una JVM de esta manera no permita una destrucción limpia de todos los servlets, para rearrancar o terminar limpiamente Apache JServ se debe usar la opción apropiada para Apache JServ, o sea: -v print server version -V print server version and details -r restart server -s stop server Por ejempo, si el shell script de Unix anterior se grabara en un fichero llamado jserv, entonces se podría rearrancar el servidor usando el comando jserv -r
Múltiples JVMsApache JServ permite tener cualquier número de JVMs. Esto puede usarse para dar soporte a seguridad mejorada, balance de carga, y tolerancia a los errores. La parte negativa es que cada JVM puede requerir recursos de memoria y procesdor significativos, lo que puede ser un factor a tener en cuenta a la hora de decidir cuantas JVMs permitir o qué hardware comprar. El lado Java de Apache JServ escucha en un puerto específico las peticiones del servidor web. Si se ejecutan diversas copias (instancias) de Apache JServ en el mismo host virtual hay que asignar a cada instancia un número de puerto diferente. El puerto se especifica en el fichero de propiedades del motor, de manera que cada instancia requiere también un fichero de propiedades del motor separado. Estos ficheros pueden ser idénticos entre ellos, excepto en el número de puerto, o bien pueden ser completamente diferentes, ya que cada JVM es independiente de las otras. Para ejecutar múltiples JVMs se neceista ejecutar Apache JServ en modo manual. La sección previa explica las diferencias entre el modo manual y el automático y muestra cómo lanzar una JVM en modo manual. La configuración de ejemplo siguiente muestra cómo configurar Apache JServ para usar diferentes JVMs para cada zona de servlets. <IfModule mod_jserv.c> ApJServManual on ApJServMount /servlets1 ajpv11://localhost:9001/jvm1 ApJServMount /servlets2 ajpv11://localhost:9002/jvm2 ApJServLogFile /usr/local/apache/logs/mod_jserv.log <Location /status/jserv/> SetHandler jserv-status order deny,allow deny from all allow from localhost </Location> </IfModule> Las peticiones que empiecen por /servlets1 serán manejadas por la zona jvm1, que escucha en el puerto 9001, mientras que las que empiecen por /servlets2 serán manejadas por la zona jvm2, que escucha en el puerto 9002. Hay que arrancar las dos instancias de la JVM, la que escucha en el puerto 9001 y la que lo hace en el 9002, de esta manera (por ejemplo): java org.apache.jserv.JServ /usr/local/apache/conf/jvm1.properties java org.apache.jserv.JServ /usr/local/apache/conf/jvm2.properties También se puede derivar el trabajo de ejecutar la JVM hacia otros ordenadores. Además, como Java está disponible para diferentes plataformas, se puede usar el mismo código sin cambios en diferente hardware sin tener que recompilar, permitiendo utilizar cualquier hardware disponible. Se puede, por ejemplo, mezclar y coordinar servidores ejecutando Windows NT, Solaris, Linux, y HP/UX en diferentes plataformas. Con modificaciones mínimas, la configuración precedente se puede usar para atender peticiones de dos máquinas diferentes (las porciones modificadas se muestran en negrita): <IfModule mod_jserv.c> ApJServManual on ApJServLogFile /usr/local/apache/logs/mod_jserv.log ApJServMount /servlets1 ajpv11://server1/zone1 ApJServMount /servlets2 ajpv11://server2/zone2 <Location /status/jserv/> SetHandler jserv-status order deny,allow deny from all allow from localhost </Location> </IfModule> En este ejemplo, peticiones que empiecen con /servlets1 serán manejadas por la instancia de Apache JServ que se ejecuta en server1, mientras que las que empiezan por /servlets2 serán manejadas por la instancia de Apache JServ que se ejecuta en server2. Se necesitará, por supuesto, instalar el lado Java de Apache JServ en cada servidor, así como configurar apropiedamente los ficheros de propiedades del motor y de la zona para cada servidor. También podría necesitarse indicar la dirección IP del servidor web en la propiedad security.allowedAddresses en cada uno de los ficheros de propiedades del motor. Además, si se usa la directiva ApJServSecretKey, se deberá guardar el fichero de la clave secreta para cada servidor (copiando el fichero o bien mediante un sistema de ficheros compartido). El balance de carga y la tolerancia a errores se añadió a Apache JServ en la versión 1.0b4. Un visión general con instrucciones están disponibles en How to: Scalability - Load-Blanacing - Fault tolerance por Bernard Bernstein y Jean-Luc Rochat. Esta funcionalidad es apropiada para sites con demandas altas (cargas elevadas) y/o que requieran fiabilidad incluso en el caso de la caída de una JVM. Otro motivo para usar JVMs, separadas es proporiconar una mayor seguridad. Aunque el separar hosts virutales en zonas separadas es suficiente mientras se puede confiar en el personal que desarrolla los servlets, puede no ser apropiado si se quiere proporcionar un mayor nivel de seguridad. Por ejemplo, se puede querer asegurar que el código escrito para un host virtual no peda acceder a ficheros mantenidos en otro host virtual. Con la configuración de ejemplo dada en una sección previa, tanto vhost1 como vhost2 compartían una sola JVM que se ejecutaba con los mismos permisos (los de usuario del servidor Apache). Para completar el aislamiento de los dos hosts virtuales hay que usar el modo manual para lanzar dos JVMs separadas. La configuración de ejemplo de los host virtuales se reproduce debajo, con los cambios para el soporte de múltiples JVMs en negrita: # directivas compartidas LoadModule jserv_module libexec/mod_jserv.so <IfModule mod_jserv.c> ApJServManual on ApJServLogFile /usr/local/apache/logs/mod_jserv_log ApJServSecretKey DISABLED <Location /status/jserv/> SetHandler jserv-status order deny,allow deny from all allow from localhost </Location> </IfModule> NameVirtualHost 192.168.1.1 # directivas para vhost1 <VirtualHost 192.168.1.1> ServerName vhost1.com DocumentRoot /usr/local/hosts/vhost1/htdocs <Directory /usr/local/hosts/vhost1/htdocs> order allow,deny allow from all </Directory> <IfModule mod_jserv.c> ApJServDefaultHost vhost1.com ApJServMount /servlets ajpv11://vhost1.com:9001/vhost1 </IfModule> </VirtualHost> # directivas para vhost2 <VirtualHost 192.168.1.1> ServerName vhost2.com DocumentRoot /usr/local/hosts/vhost2/htdocs <Directory /usr/local/hosts/vhost2/htdocs> order allow,deny allow from all </Directory> <IfModule mod_jserv.c> ApJServDefaultHost vhost2.com ApJServMount /servlets ajpv11://vhost2.com:9002/vhost2 </IfModule> </VirtualHost> También se necesitará un fichero de propiedades del motor para cada maquina. Los ficheros pueden ser idénticos, excepto en el puerto, que debe ser el apropiado para cada JVM. Por ejemplo, un fichero de propiedades muy simple para vhost1. security.allowedAddresses=192.168.1.1 security.authentication=false port=9001 zones=vhost1 vhost1.properties=/usr/local/apache/conf/vhost1.zone.properties El fichero de propiedades de vhost2 es casi idéntico: security.allowedAddresses=192.168.1.1 security.authentication=false port=9002 zones=vhost2 vhost2.properties=/usr/local/apache/conf/vhost2.zone.properties Para completar el ejemplo, cada JVM debe ser lanzada como un usuario diferente. En Unix, se puede usar el comando su para lanzar la JVM con el usuario que se quiera. Por ejemplo: % su - user1 -c \\ "java -classpath $CLASSPATH:/usr/local/jsdk/lib/jsdk.jar:/usr/local/jserv/lib \\ ApacheJServ.jar org.apache.jserv.JServ \\ /usr/local/apache/conf/vhost1.engine.properties" % su - user1 -c \\ "java -classpath $CLASSPATH:/usr/local/jsdk/lib/jsdk.jar:/usr/local/jserv/lib \\ ApacheJServ.jar org.apache.jserv.JServ \\ /usr/local/apache/conf/vhost2.engine.properties" También ser podría redireccionar la salida de cada instancia a un fichero de log, y/o usar las propiedades de log en cada fichero de propiedades del motor para dirigir los mensajes de log a los ficheros apropiados.
URL de estadoApache JServ incluye un gestor especial y un servlet interno que se puede usar para monitorizar el servidor a través del navegador web. Si se usa la configuración de ejemplo proporcioanda con Apache JServ, entonces la URL para mostrar la página de estado es http://localhost/jserv/ (la barra final es necesaria). En el fichero de propiedades del motor también se puede habilitar la funcionalidad completa de estado añadiendo la siguiente propiedad: security.selfservlet=true que autoriza el acceso a la información sobre las zonas de servlets mapeadas. La URL de estado da una página que lista los hosts configurados y los motores de servlet. Cada host configurado corresponde o bien al host por defecto del servidor web o bien a un host virtual. Cada motor de servlets mapeado corresponde aun motor de servlets distinto, tal como se haya especificado con la directiva ApJServMount directives en httpd.conf. Haciendo click en uno de los hosts configurados se muestra información sobre ese host, incluyendo directivas de configuración, puntos de montaje y extensiones de fichero. Haciendo click en uno de los motores de servlets mapeados permite revisar la JVM, la ruta de clases (class path) y varios parámetros más, así como la configuración individual de cada zona. En general, para habilitar el gestor de estado de Apache JServ hay que añadir una directiva Location en httpd.conf con una directiva SetHandler anidada, especificando le gestor jserv-status. Se puede mantener un estilo uniforme para todos los URL de estado (p. e., para Apache JServ, mod_perl, etc.) de manera que todos los URL de ese tipo empiecen con /status/; de esa manera se utilizaría una directiva Location como la siguiente: <Location /status/jserv/> SetHandler jserv-status order deny,allow deny from all allow from localhost </Location> Se puede acceder a la URL de estado desde la máquina que aloja el servidor web usando una URL como http://localhost/status/jserv/. (la barra final es necesaria)
Solución de problemasApache JServ es una aplicación compleja. Una instalación y configuración exitosa requierent que tanto el servidor web Apache como el módulo JServ y una JVM estén correctamente instalados y configurados. Cada una de estas tareas implica varios subsistemas, incluyendo redes, permisos de fichero y de acceso, diferentes ficheros de configración y varias directivas de configración. Incluso usuarios experimentados se pueden confundir con tal cantidad de factores entrelazados. El proyecto Java Apache incluye una comunidad de desarrolladores y usuarios experimentados. El web site del proyecto (http://java.apache.org) incluye, entre otras cosas, una cantidad significativa de información sobre Apache JServ. La página de FAQs on-line, mantenida por usuarios, y accesible desde la página inicial, es un recurso excelente. Hay temas de configuración y organización que yo no he tenido oportunidad de abordar, pero una revisión rápida de la constantemente creciente FAQ suele proporcionar una respuesta. La lista de correo es también un recurso excelente (para detalles ver el web site). Ficheros de registro (log)Las principales fuentes de información cuando se revisan los problemas de configuración son la URL de estado (descrita en otra sección) y los ficheros de registro del servidor (server log files). Antes de saber que ha pasado, habrá que habilitar el registro y examinar las entradas resultantes en los ficheros de registro. Entre Apache y Apache JServ hay unos cuantos ficheros de registro. Intentar hacer lo mejor que pueda para resumir qué contiene cada uno de ellos. Entre parentesis indico los nombres recomendados para cada fichero. Registro de accesos (access.log)
Registro de errores (error.log)
Registro de mod_jerv (mod_jserv.log)
Registro de Apache JServ (jserv.log)
Podría ser necesario tener que mirar en todos los ficheros anteriores para encontrar la fuente de un problema. Para habilitar registro en Apache se necesitan unas pocas directivas en httpd.conf (que vienen habilitades en la instalación por defecto), como por ejemplo: LogLevel warn LogFormat "%h %l %u %t \\"%r\\" %>s %b" common CustomLog /usr/local/apache/logs/access.log common ErrorLog /usr/local/apache/logs/error.log Para habilitar el fichero de registro de mod_jserv se necesita tener la directiva ApJServLogFile en httpd.conf. Por ejemplo, ApJServLogFile /usr/local/apache/logs/mod_jserv.log Si se usa la marca DISABLED en vez de un nombre de fichero, entonces los mensajes se redirigirán al fichero de registro de errores (error log) de Apache, lo que puede facilitar un poco el seguimiento de errores, ya que habrá un fichero menos a monitorizar. Para habilitar el fichero jserv.log hay que habilitar las directivas apropiadas en el fichero de propiedades del motor. Por ejemplo: log=true log.file=/usr/local/apache/logs/jserv.log log.timestamp=true log.dateFormat=yyyyMMdd.HHmmss.SSS: log.channel.init=true log.channel.terminate=true log.channel.serviceRequest=true log.channel.authentication=true log.channel.requestData=true log.channel.responseHeaders=true log.channel.signal=true log.channel.exceptionTracing=true log.channel.servletManager=true log.channel.singleThreadModel=true Un problema común son las restricciones en los permisos de acceso a los ficheros de registro, que no permiten al lado Java de Apache JServ escribir en su fichero de registro. El fichero jserv.log debe poder ser escrito por el usuario mediante el cual se identifica la JVM. En el modo automático esto significa que el fichero debe poder ser escrito por el usuario o grupo por el cual se identifica el servidor Apache, normalmente el usuario nobody. Si se ejecuta en Unix, las directivas de User y Group están puestas como usuario y grupo nobody, por lo que se puede necesitar hacer lo siguiente antes de generar el fichero jserv.log: mkdir /usr/local/apache/logs chgrp nobody /usr/local/apache/logs chmod ug+rwx /usr/local/apache/logs ls -ld /usr/local/apache/logs drwxrwxr-x 2 root nobody 1024 Jun 10 18:58 /usr/local/apache/logs/ Los ficheros de registro crecen bastante, y pueden contener mucha información que no es relevante para la tarea que se esté haciendo. Una manera de asegurarnos que sólo estamos viendo información esencial es limpiar los ficheros de registros y después hacer una prueba para regenerarlos sólo con la información relevante. Esto se puede hacer parando Apache, borrando los ficheros de registro viejos, y luego rearrancando apache. Hecho esto, se puede hacer una petición simple que genere un error. Por ejemplo, pongamos que el problema está en la URL http://localhost/servlets/HelloWorldServlet. Entramos esta URL en el navegador e intentamos acceder. En ese momento tenderemos ficheros de registro conteniendo sólo la información absolutamente relevante. Antes de hacer nada más, se pueden examinar y/o copiar los ficheros de registro. Un método excelennte para analizar problemas es monitorizar continuamente los ficheros de registro. En Unix, se puede usar el comando tail -f para mostrar las entradas a medida que se escriben en los registros. Si además se está utilizando X Windows, entonces se pueden abrir múltiples ventanas de terminal, cada una de las cuales puede ser utilizada para monitorizar un fichero de registro diferente. A continuación hay un script de ejemplo que se puede utilitzar para monitorizar los ficheros de registro: #!/usr/bin/perl
$loc=10;
$logdir="/usr/local/apache/logs";
$options="-bg black -fg green -font fixed -e tail -f";
foreach $file ("access.log", "error.log", "mod_jserv.log", "jserv.log")
{
system "xterm -geometry \\"100x10+5+$loc\\" \\
-T $logdir/$file $options $logdir/$file &";
$loc += 180;
}
Se puede hacer más divertido combinando el comando tail con grep. Por ejemplo, se pueden examinar sólo comandos específicos (suponiendo, por ejemplo, que el programa registre el texto "SQLUpdate" junto a la información deseada): tail -f /usr/local/apache/logs/error.log | grep SQLUpdate Windows no tiene comandos como tail o grep. Lo mejor que he podido hacer bajo "vainilla Windows" ha sido cargar los ficheros de registro en el Bloc de Notas. Desgraciadamente, esto requiere recargar los ficheros cada vez que se quieran comprobar nuevos datos. Los puertos de Cygnus de varias utilidades GNU son mucho mejores, convenientemente envueltas en el paquete de utilidades Cygwin http://sourceware.cygnus.com/cygwin. Estas utilidades incluyen tail, grep y bash (un muy competente shell de Unix que sume el prompt de Windows en la más absoluta vergüenza). Si no se sabe interpretar lo que pone en los ficheros de registro o cómo fijar las cosas, entonces se puede mirar en el código fuente de Apache JServ. Si se sabe leer código Java, entonces probablemente se puede uno imaginar lo que se espera que se ponga en los ficheros de configuración. También se puede mirar en el código fuente de mod_jserv, especialmente las fuentes de wrapper ((jserv_wrapper.c, jserv_wrapper_unix.c, and jserv_wrapper_win.c), que manejan el lanzamiento de la JVM en el modo automático Problemas de arranqueIntenta ejecutar Apache Jserv en modo manual. La ejecución en modo manual permite el aislamiento del alcance de un problema. Si se puede arrancar la JVM en modo manual, entonces el problema estará en la configuración o en la organización de mod_jserv, esto es, el módulo mod_jserv no se carga o bien las indicaciones en httpd.conf no son correctas. Si no se puede ejecutar en modo manual, entonces el problema está en jserv.properties, en una de las zonas de propiedades o almacenes o en la configuración de Java en el ordenador. Conflictos de puertosUn problema común de arranque viene causado por un conflicto de puertos. Si se intenta arrancar Apache JServ mientras un proceso existente, típicamente otra instancia de Apache JServ, está ya ligado al mismo puerto, entonces se producirá el siguiente mensaje de error en el fichero de registro de mod_jserv (o en la salida del runtime de Java si se ejecuta en modo manual): ApacheJServ/1.0b5: Exception creating the server socket: java.net.BindException: Address already in use Para resolver este conflicto, se puede intentar ejecutar Apache JServ en un puerto diferente, cambiando la indicación de puerto en la directiva ApJServMount del fichero httpd.conf, y en la propiedad port en el fichero de propiedades del motor. También se debería comprobar la lista de procesos para ver si otra instancia de Apache JServ está ligada al mismo puerto. Permisos de ficherosOtra fuente común de problemas viene dada por los permisos de los ficheros, que no permiten acceso a los recursos que se piden. Se debería comprobar que el usuario como el que se ejecuta Apache JServ tiene acceso al fichero ApacheJserv.jar y a los ficheros de propiedades del motor y de la zona. Este usuario debería tener permiso de escritura en el fichero jserv.log. Si, por ejemplo, el usuario no tiene acceso al fichero ApacheJServ.jar entonces el fichero error.log tendría entradas como las siguientes: /usr/local/jserv/lib/ApacheJServ.jar: Permission denied Can't find class org.apache.jserv.JServ Si el directiorio que contiene el fichero jserv.log file no puede ser escrito, entonces el fichero error.log puede contener entradas como: ApacheJServ/1.0b5: Error opening log file: java.io.IOException: Directory not writable: /usr/local/apache/logs y al mismo tiempo, el fichero mod_jserv.log contendría entradas genéricas tales como: [20/05/1999 13:04:00:044] (INFO) wrapper: Java VM restarting (PID=1690) [20/05/1999 13:04:00:046] (INFO) wrapper: Java VM spawned (PID=1953, PPID=1690) [20/05/1999 13:04:01:054] (INFO) wrapper: Java VM exited (PID=1690)
Desarrolladores múltiplesLos requerimientos para dar soporte a múltiples desarrolladores trabajando en un solo proyecto usando Apache Jserv son similares a los requerimientos necesarios para dar soporte a multiples clientes como ISP, excepto en que probablemente no habrá que estar excesivamente preocupado con la seguridad entre los desarrolladores. Cada desarrollador debería tener su zona de servlets propia. Esto permite a cada uno instalar y probar cambios sin afectar a lo que haga el resto. En una instalación básica, se debería usar un sólo servidor web Apache, sin hosts virtuales y con Apache JServ ejecutándose en modo automático. Cada desarrollador tendría asignada su propia zona de servlets, nombrada de alguna manera lógica, como: ApJServMount /alice/servlets /alice ApJServMount /bob/servlets /bob Otra manera de proporcionar esta funcionalidad es asignar a cada desarrollador un host virtual separado. Esto no ofrece ventajas específicas sobre el tener zonas separadas, pero puede proporcionar mayor flexibilidad a cada desarrollador para personalizar su entorno. Otra configuración podría dar a cada desarrollador acceso a una instalación privada de Apache. Si los servidores están localizados y mantenidos en un solo servidor (por ejemplo para acceder a ficheros de datos o de configuración compartidos) entonces cada servidor deberá ser ejecutado con un número de puerto diferente (8080,8081, 8082, etc.). El desarrollador podrá entonces arrancar y parar el servidor Apache sin afectar a otros desarrrolladores y sin necesitar asistencia de un administrador del sistema. Alternativamente, los servidores pueden ser ejecutados en cada una de las máuinas locales de los desarrolladores, permitiendo asi al dessarrollador un control total sobre el servidor.
SeguridadLas facilidades de seguridad proporcionadas por Apache y Apache JServ son accesibles a varios niveles. Estos se pueden dividir aproximadamente entre protecciones de comunicación y protecciones internas de Java. En el nivel más externo se pueden filtrar los accesos a Apache y a Apache JServ usando un firewall o alguna otra herramienta externa. En el nivel siguiente, el servidor web Apache incluye características para limitar el acceso a URL específicas. Se puede usar la directiva Location y el control de acceso usando los ficheros htaccess para limitar el acceso a las URL que ejecutan los servlets. Por ejemplo, para proteger un conjunto de servlets para acceso sólo desde un dominio y usuario particular, se puede usar una directiva Location como la siguiente: <Location /private-servlets> order deny,allow deny from all allow from .domain.com require user foo AuthType Basic AuthName private AuthUserFile /usr/local/apache/conf/users </Location> Este ejemplo restringe el acceso a las URL que empiecen con /private-servlets, lo que correspondería al punto de montaje para la zona de servlets a la que se le quiere restringir el acceso. Sólo el usuario foo accedientdo al site desde una máquina en el dominio .domain.com podrá acceder al sitio protegido. Para más información de la protección de URL, ver la documentación de Apache, para, por ejemplo, añadir usuarios o grupos adicionales o para usar un método de autenticación diferente. Más allá del servidor web está el nivel de comunicación entre el servidor web y Apache JServ. Incluso si se protege completamente el acceso al servidor web aún se necesitará proteger el acceso al motor de servlets. Se puede limitar especificando las direcciones IP desde las que se podran aceptar conexiones usando un fichero de claves secreto, conocido sólo por el motor de servlets y por los clientes de confianza (trusted clients). Para limitar las direcciones IP se usa la propiedad security.allowedAddresses en el fichero de propiedades del motor. Por ejemplo, para añadir la siguiente línea security.allowedAddresses=192.168.1.2,196.168.1.3 daría acceso al motor de servlets sólo desde las direcciones IP indicadas. Se puede añadir seguridad adicional usando un fichero de claves secretas y un string de cambios generado aleatoriamente. Ambas características estan activadas en el fichero de propiedades del motor: security.authentication=true security.challengeSize=5 security.secretKey=/usr/local/apache/conf/jserv.secret.key El fichero de claves secretas debe ser conocido también por el cliente Apache Jserv (mod_jserv), así que hay que incluir la directiva ApJServSecretKey en el fichero httpd.conf: ApJServSecretKey /usr/local/apache/conf/jserv.secret.key El fichero de claves secretas debe contener datos aleatorios. Debería ser sólo legible por mod_jserv y el motor de servlets. Una limitación de esta aproximación es que cualquier código Java ejecutado por el motor de servlets puede leer el fichero de claves secretas, así que sólo a personal de confianza se le debería permitir instalar servlets. En Apache JServ se puede gestionar la seguridad usando múltiples zonas de servlets para separar código y objetos. El código ejecutado dentro de una zona no tiene acceso al código ejecutado en cualquier otra zona, e inclose se pueden usar zonas de servlets para particionar rutas de clases (class path), ya que las clases incluides en el almacén de una zona no son accesibles por otra zona (a menos que las clases se añadan explícitamente a esa zona). Cuando se usa una sola JVM, el código ejecutado en Apache JServ tiene acceso a recursos del sistema y de disco. Se puede dar más seguridad ejecutando múltiples copias de Apache JServ en JVMs completamente separadas. Cada JVM se ejecuta en su propio entorno de proceso y puede ser ejecutada con identificador de usuario único, lo que permite el uso de protecciones del sistema operativo a nivel de fichero y procesos Java se diseño para ser un lenguaje seguro, e incluye métodos propios para limitar las operaciones que el código puede hacer. También incluye un sistema de tipos seguro y un verificador bytecode que permite que sólo se ejecute código valido. Es más dificil crear accidentalmente agujeros de seguridad en Java que en otros lenguajes populares (por ejemplo, a través de metaevaluaciones de entradas del usuario o por errores de sobrecarga del buffer). Por supuesto, aún es posible escribir software inseguro en Java, es sólo que el lenguaje en sí es menos propenso a ser la fuente del problema. Java incluye métodos propios para prevenir operaciones no autorizadas. Las maquinas de los usuarios, donde se ejecutan los applets de Java, siempre han estado protegidas por estas características de segurirad. El servidor, donde se ejecutan los servlets, no ha tenido en cambio este nivel de protección, así que los servlets de Java y otro código Java ejecutado en el servidor no ha sido restringido por estrictas políticas de seguridad. Es posible, al menos teóricamente, añadir un gestor de seguridad (JDK 1.1) o bien personalizar una política de seguridad (JDK 1.2) para Apache JServ. En el JDK 1.2 es posible especificar una política de seguridad personalizada para cargarla en la JVM. Cualquiera puede desarrollar una política apropiada para su entorna, aunque la documentación de Sun no es tan fácil de seguir como uno esperaría. Hasta la fecha, no hay ningún gestor de seguridad o política de seguridad en Apache JServ, aunque hay planes para añadir esa funcionalidad en futuras versiones.
DepuraciónSe pueden usar los metodos de registro en javax.servlet.ServletContext para registrar los mensajes en el fichero de registro de Apache JServ (p.e., jserv.log), o incluso escribir directament en System.err o System.out. Se puede hacer mucha depuracion con los comandos de log, aunque puede ser algo tedioso y puede ser mejor usar un depurador real. El lado Java de Apache Jserv se ejecuta como un aplicaci´on Java con un metodo main estatico en la clase org.apache.jserv.JServ. Los servlets se ejecutan dentro de esta aplicacion, lo que significa que se puede usar cualquier depurador de Java para depurar Apache JServ y los servlets. El JDK de Sun incluye el depurador jdb. Para usar jdb, se puede arrancar Apache JServ en modo manual (ver la seccion de ejecucion del modo manual para mas detalle). En resumen, para ejecutarlo en modo manual, hay que poner la propiedad ApJServManual en on en httpd.conf, y luego ejecutar manualmente Apache JServ desde la linea de comandos. Se puede adaptar el siguiente codigo de shell script de Unix para lanzar Apache JServ en modo manual usando jdb. #!/bin/sh properties=/usr/local/apache/conf/jserv.properties log=/usr/local/apache/logs/jserv_manual.log CLASSPATH=$CLASSPATH:/usr/local/jsdk/lib/jsdk.jar CLASSPATH=$CLASSPATH:/usr/local/jserv/lib/ApacheJServ.jar jdb org.apache.jserv.JServ $properties
Afinar el rendimientoLas dos pérdidas principales de rendimiento de Apache JServ se deben al registro y a la rellamada automática de clases. Gran parte del retraso del registro (logging) se debe a los muchos objetos creados y gestionados para el registro. La rellamada automática de clases puede ser particularmente lenta si hay bastantes ficheros de clase separados. Para deshabilitar el registro en el lado Java, hay que establecer a false la propiedad log en el fichero de propiedades del motor. Para deshabilitar la rellamada autmática de clases, hay que poner a false las propiedades autoreload.classes y autoreload.file en el fichero de propiedades de la zona. Otro sumidero de rendimiento es el pequeño tamaño máximo e inicial para los procesos que tienen por defecto algunas JVMs. Esto resulta en una recolección dememoria excesiva y/o en una cambio de tamaño del heap. En el modo automático se pueden usar las propiedades de wrapper.bin en el fichero de propiedades del motor para pasar valores para las opciones -ms y -mx al runtime de Java. Por ejemplo, wrapper.bin.parameters=-ms32m wrapper.bin.parameters=-mx128m (para más opciones, consultar la documentación del propio runtime de Java.) Se pueden deshabilitar algunas de las características de autenticación de seguridad en Apache JServ. Eliminando la propiedad security.secretKey y estableciendosecurity.authentication a false, se puede eliminar el tiempo gastado en conexiones de autenticación entre el cliente Apache JServ y el servidor. Sólo se debería eliminar esta autenticación, sin embargo, si se está seguro que se protege la instalación por otros métodos y/o si la ganancia en el rendimiento justifica la pérdida en seguridad. También se puede ganar un rendimiento adicional optimizando el código Java propio. Dos herramientas útiles para perfilar son OptimizeIt! de Intuitive System yJInsight de IBM. OptimizeIt trabaja mejor con JDK1.2, dado que tiene una instrumentación más avanzada que JDK1.1. Si afinando Apache JServ y optimizando el código propio no se han obtenido las ganancias de rendimiento buscadas, entonces se puede investigar el usar una JVM diferente. Cualquier JVM compatible con JDK 1.1 puede ser usada con Apache JServ. Sun, IBM y Microsoft hacen JVMs competitivas. Los vendedores están todos mejorando el rendimiento de las JVMs. Por ejemplo, Sun lanzó HotSpot en Abril de 1999, que ofrece mejoras de rendimiento sobre la JVM normal de Sun y se orienta principalmente a Java para servidores. También se puede explorar la compilación a código nativo, que compila fuentes Java o bytecodes a código máquina nativo. EWl producto líder actualmente para compilación a código nativo es TowerJ http://www.towerj.com de Tower Technologies. La compilación a código nativo, sin embargo, puede dar mucho trabajo y sermenos flexible que los bytecodes portables de Java. Con el balance de carga se puede dividir la carga entre múltiples servidores. Esta aproximación, sin embargo, comporta varios temas administrativos que no estan presentes con un solo servidor. Comprar hardware mejorado es probablemente una solución más simple que intentar mantener múltiples servidores, pero el balanceo de la carga puede ser, en cambio, el único método para conseguir el rendimiento que se necesita. Una visión general, con instrucciones de configuración, se encuentra en How to: Scalability - Load-Blanacing - Fault tolerance por Bernard Bernstein y Jean-Luc Rochat.
Funcionalidades añadidasBy installing Apache JServ on your server you have increased your options for server-side software. A growing number of Java servlets and generic Java libraries are being developed. You can write your own servlets from scratch, or you can integrate existing servlets into your environment. Page Compilation ServletsUna categoría muy util de servlets, conocidos como page compilation servlets, se pueden usar para añadir contenido dinámico a un site. Estos servlets analizan el fichero fuente, extraen e interpretan unos tags (marcas) especiales y generan una salida que es una combinación del fichero original y los tags interpretados. Un servlet típico de compilación de páginas es Apache JSSI. Éste es un producto del proyecto Java apache que proporciona inclusiones de servidor para servlets de Java (Apache JSSI se puede bajar de http://java.apache.org.) Se puede añadir fácilmente contenido dinámico a un documento HTML ya creado añadiendo un tag 'servlet' especial. Apache JSSI ejecuta el servlet especificado por el tag y reemplaza el tag con la salida del servlet. Por ejemplo, asumiendo que se ha instalado Apache JSSI y un serlvet llamado DateServlet que escribe la fecha actual, en el siguiente ejemplo se ve cómo incrustar la salida del servlet en un fichero HTML: <html> <head> <title>Fecha</title> </head> <body> <h1>Fecha</h1> <servlet name="DateServlet"> </servlet> </body> </html> La salida después de acceder la página anterior podría ser <html> <head> <title>Fecha</title> </head> <body> <h1>Fecha</h1> 11 de Abril de 2001 </body> </html> (el texto substituido se muestra en negrita) Los servlets de compilación de páginas extraen la localización del fichero a analizar de la información de ruta extra que hay en la URL: cuando se hace una petición de un fichero que se ha de servir a través de un servlet de este tipo. la URL es algo así como esto: http://dominio/zona/servlet/ruta donde zona es el punto de montaje de la zona de servlets, servlet es el nombre del serlvlet de compilación de páginas, y ruta es la ruta relativa al fichero a compilar. Por ejemplo, usando Apache JSSI, http://dominio/servlets/org.apache.servlet.ssi.SSI/products/file.html Esta URL pasaría la ruta /products/file.html al servlet Apache JSSI, que entonces devolvería cualquier código HTML del fichero original así como el resultado de la ejecución de cualquier servlet incrustado (mediante el tag servlet) Si se quiere que el servlet de compilación de páginas pueda manejar ficheros en cualquier localizacón arbitraria del servidor web, entonces hay que añadir un gestor de manera que Apache JServ pueda pasar cualquier fichero acabo en un sufijo particular al servlet de compilación de páginas. Para hacer esto, hay que añadir una directiva ApJServAction al fichero httpd.conf. Por ejemplo, ApJServAction .jhtml /servlets/org.apache.servlet.ssi.SSI Ahora cada vez que un documento acabado en .jhtml sea pedido, Apache JServ invoacara al servlet Apache JSSI. Una vez se tienen documentos con un sufijo particular servidos a través del servlet de compilación de páginas, se podria añadir una entrada a la directiva DirectoryIndex en el fichero de configuración de Apache (httpd.conf), de manera que se pueda usar un fichero como ese como el fichero por defecto de un directorio. Por ejemplo, DirectoryIndex index.html index.jhtml En general, usar un sufijo especial es la manera preferida para invocar un servlet de compilación de paginas. Usar un sufijo es mejor que usar URLs que contengan una zona de servlets y el nombre del servlet porque esconde detalles internos del servidor a los usuarios. Si no se quiere usar un sufijo especial (por ejemplo si se está añadiendo contenido dinámico a un site existente) entonces se puede usar mod_rewrite para reescribir URLs que contienen el sufjio .html a URLs que invoquen el servlet en cuestión. Para ver un ejemplo de este tipo de aplicación, ver la sección de uso de mod_rewrite con Apache JServ). JavaServer PagesCon JavaServer Pages (JSP) se puede incrustar código Java directamente en un documento HTML. El código Java se compila automáticament cuando el fichero que lo contiene se modifica, los bytecodes compiladors se ejecutan entonces a través de la JVM y la salida es entregada por el servidor web junto con el código HTML que la rodeaba. JSP proporciona integración entre el código Java y HTML, la especificación y una referencia de implementación se pueden encontrar en el sitio web de Java de Sun, en http://java.sun.com/products/jsp. Hay como mínmo dos implementacions libres y públicamente accesibels de programas que permiten incrustar código Java en documentos HTML: GNU Server Pages (GSP) y GNU JavaServer Pages (GNUJSP). Estos productos son esfuerzos de desarrollo independientes. Desde que la versión 1.0 de la especificación de Sun de las JSP salió recientemente, ninguno de los productos se adapta aún a ella, pero se pueden utilizar estos programas para desarrollar paginas web. Tanto GSP com GNUJSP estan escritos como servlets de Java normales, lo que significa que deberían trabajar con cualquier motor compatible de servlets en cualquier sistema operativo. Además de estos programas libres hay también implementaciones comerciales de JSP. GSPEsta sección muestra cómo se puede añadir GSP a una instalación de Apache JServ. El añadir GSP ilustra diversos puntos, incluyendo servlets de compilación de paginas, mapeo de sufijos de ficheros y uso de ficheros de propiedades y registro (log) para un servlet (por supuesto, se puede usar cualquier otro servlet de compilación de páginas con Apache JServ). GSP se puede bajar del website de Bitmechanic http://www.bitmechanic.com. Las siguientes instrucciones ser refieren a la versión 0.86 de GSP, que es la versión corriente más accesible a la hora de escribir esto. Configurar GSP consiste en:
Estos pasos se explican con más detalle debajo. 1. Crear el directorio de clases GSP necesita un directorio en el que pueda escribir dinámicamente los ficheros de clase compilados, por ejemplo /usr/local/apache/gsp-classes, pero se puede poner este directorio donde se quiera. Por ejemplo, si se estan configurando múltiples hosts virtuales, se podría poner esto de manera que cada host virutal tuviera su propio directorio. Este directorio necesita poder ser escrito por el usuario como el qual se ejecuta Apache JServ (p.e. nodoby). 2. Añadir propiedades al fichero de propiedades de la zona La necesaria configuración de los servlets puede ser hecha añadiendo las siguientes líneas al fichero de propiedades de la zona. Se necesitará, por supuesto, ajustar los paths para que se correspondan con las localizaciones de los ficheros de nuestro sistema. repositories=/usr/local/java/gsp-0.86/gsp-0.86.jar repositories=/usr/local/apache/gsp-classes servlet.gsp.code=com.bitmechanic.gsp.GspServlet servlet.gsp.initArgs=propfile=/usr/local/apache/conf/gsp.prop erties 3. Crear el fichero de propiedades de GSP GSP usa su propio fichero de propiedades. Las propiedades de ejemplo que vienen con GSP incluyen comentarios que explican las directivas. A continuación hay un fichero de ejemplo gsp.properties. logger.filename=/usr/local/apache/logs/gsp.log parser.classdir=/usr/local/apache/gsp-classes parser.javac=/usr/local/java/jdk/bin/javac parser.extraclasspath=/usr/local/java/gsp/gsp- 0.86.jar:/usr/local/apache/gsp-classes parser.classreloader=com.bitmechanic.gsp.GspClassLoader 4. Añadir la directiva ApJServAction a httpd.conf Para que cualquier documento acabado en .gsp sea procesador por GSP hay que añadir la siguiente directiva a httpd.conf: ApJServAction .gsp /servlets/gsp Para permitir también índexar el directorio usando .gsp hay que añadir una entrada para .jsp a la directiva DirectoryIndex en httpd.conf, por ejemplo: DirectoryIndex index.html index.gsp 5. Prueba Rearrabcar Apache, y probar entonces la instalación de GSP copiando los ficheros .gsp del directorio de pruebas de la distribución a nuestro directorio raíz de documentos y luego acceder a los documentos. Por ejemplo, cp /usr/local/java/gsp/examples/date_test.gsp /usr/local/apache/htdocs lynx http://localhost/date_test.gsp Esto podría no ejecutarse correctamente la primera vez, y entontces se debería buscar errores en los ficheros de configuración (httpd.conf, propiedades del motor, propiedades de zona y propiedades de GSP). Cuando se buscan los errores, no hay que olvidar mirar en todos los ficheros de registro (.log), incluyendo el fichero de registro de GSP, especificado en la propiedad logger.filename en el fichero de propiedades de GSP.
ConclusiónApache JServ todavía está en una versión beta mientras esto se escribe, aunque la versión final v1.0 está previsto que salga el 14 de Junio. La versión 1.0 sólo soporta JSDK2.0, ya que JSDK2.1 se lanzó mientras Apache JServ todavía estava en desarrollo (beta). Se planea un soporte completo para JSDK2.1 para la próxima release, y de hecho ya se está trabajando para tener una completa compatibilidad. También hay algunos esfuerzos en marcha para mejorar la funcionalidad y respuesta de Apache JServ. Apache JServ es un motor de servlets flexible, de código abierto (open-source), disponible para muchos tipos de sitios. La gran base de usuarios del servidor web Apache y la creciente popularidad de Java prácticamente aseguran un interés continuado en Apache JServ. Como proyecto de código abierto, tienes acceso completo al código fuente y puedes corregir errores y enviar parches directamente al grupo, o, si demuestras interés y una habilidad razonable, directamente a los archivos de código fuente. El proyecto Java Apache ha evolucionado desde su meta inicial de crear el motor de servlets Apache JServ, y ahora actúa como un cobertor para diferentes proyectos de código abierto en Java. Un grupo entusiasta e informado de desarrolladores y usuarios mantiene los proyectos en permanente evolución y provee una valiosa asistencia.
RecursosProyecto Apache http://www.apache.org Proyecto Java Apache http://java.apache.org JSDK de Sun http://java.sun.com/products/servlet/index.html JavaServer Pages de Sunhttp://java.sun.com/products/jsp GNU Server Pages (GSP) http://www.bitmechanic.com GNU JavaServer Pages (GNUJSP) http://www.klomp.org/gnujsp Intuitive System's OptimizeIt! http://www.optimizeit.com IBM's JInsight http://alphaworks.ibm.com/tech/jinsight Service monitoring daemon http://www.kernel.org/software/mon Utilidad Cygwin de Cygnushttp://sourceware.cygnus.com/cygwin TowerJ http://www.towerj.com Ari Halberstadt, 1999 (ari@shore.net) |