Algunos apuntes sobre Lucene en el mundo de Alfresco

En este artículo quiero hablaros de Lucene. Aunque en la versión 4.0 de Alfresco ya se incorpora SOLR como motor de indexación alternativo y escalable, también se puede seguir usando Lucene. Además, existen multitud de instalaciones que utilizan Lucene y que posiblemente seguirán utilizándolo. Voy a ampliar algunos conceptos al respecto para intentar ayudaros a comprender cómo funciona y cómo solucionar posibles problemas que nos podemos encontrar.
  • NOTA/DISCLAIMER: Lo que aprendas en este artículo no lo uses en producción salvo que sepas realmente lo que estás haciendo. No me hago responsable de los problemas que puedas tener derivados de este artículo 😉
Empecemos por el principio, el documento. Hay dos partes de un documento en Alfresco, la primera es el documento por si mismo y su contenido, la segunda son los metadatos asociados a ese documento. Por defecto, se indexan esas dos partes de un documento, por eso podemos buscarlos y localizarlos. Esta es una explicación simple ya que por debajo hay una serie de tareas automáticas y un poco más complejas que la descripción anterior. Vamos a verlo.
  • En Alfresco puedes buscar información mediante las interfaces web Share o Explorer y también mediante las diferentes APIs disponibles. Las búsquedas pueden ser por palabras clave o búsquedas booleanas, Alfresco las traduce a formato Lucene Query y las ejecuta sobre los índices en su instancia de Alfresco.
  • ¿Cómo puedo saber que hay realmente en los índices de Alfresco? Los índices por defecto se almacenan en un directorio llamado “lucene-indexes” dentro del directorio “alf_data“. Dentro del directorio principal de índices hay más carpetas y ficheros que están relacionados con los índices de los que no podemos ver su contenido directamente ya que son binarios y de los que hablaremos más adelante.
  • Puedes ver el contenido de esos ficheros con una herramienta de debug muy útil y multiplataforma llamada Luke. Para abrir los índices por ejemplo del workspace/Spacestore, en el browser de Luke navega hasta alf_data/lucene-indexes/workspace/SpacesStore y selecciona el fichero IndexInfo. Luke te permite abrir los índices con la opción “Open in Read Only mode”, úsala. Ya que con Luke puedes hacer tareas de lectura sobre los índices y también ¡borrados! Lee bien la documentación antes de aventurarte a hacer alguna fechoría con esta herramienta. No es el objetivo de este artículo hacer un manual de Luke, simplemente darlo a conocer si no lo conocías ya. Si lo usas y lo dominas puedes escribir un artículo que será muy útil para todos.

Sigamos con los índices. Veamos qué hace Alfresco de forma genérica cuando se sube un documento o se actualiza:
Como vemos en la imagen anterior, a ese diagrama global podríamos añadir el siguiente resumen del proceso de indexación:
  • 1º Se transforma el contenido a texto
  • 2º Se usa un analizador basado en el idioma del documento para extraer cadenas derivadas de plurales, mayúsculas, etc. Dependiendo del idioma, estos analizadores serán más o menos complejos.
  • 3º Lucene indexa los metadatos que están marcados para ser indexados.
  • 4º Lucene indexa el contenido, que sea susceptible de indexar (por ejemplo un documento, si se trata de un binario como una imagen no se indexa el contenido). La indexación del contenido se podría desactivar.
  • 5º Si se trata de una actualización, la versión anterior se mueve a otro directorio (interno de los índices) y la nueva versión se crea en el índice activo (live index).
Hay tres directorios que afectan a los índices y que se pueden configurar en alfresco-global.properties mediante las siguientes propiedades (recuerda que se configuraría usando propiedad=valor y todas las opciones está disponibles en el fichero alfresco/WEB-INF/classes/alfresco/repository.properties):
  • dir.idexes y dir.indexes.lock que necesitan estar en los discos locales donde se instala el repositorio (alfresco.war), ya que se hace un uso intensivo de I/O de disco.
  • dir.indexes.backup podemos ubicarlo donde queramos siempre que esté accesible por el servidor, ahí se almacenan los backups automáticos nocturnos a las 3AM cada día. Aunque también se puede ejecutar manualmente mediante JMX en la versión Enterprise. Si quieres saber qué procesos nocturnos afectan a los índices y cómo, lee este artículo. No tener controlados los backups de los índices te pueden llevar a tener que reindexar todo un repositorio completo, que puede llevar varios días dependiendo de la cantidad de contenidos.
Dentro del directorio dir.indexes hay una serie de directorios que corresponden a cada uno de los stores de Alfresco (más info aquí). Cada directorio o subdirectorio contiene un fichero llamado IndexInfo que nos da información sobre los índices de cada uno de los stores.
La indexación de los contenidos se gestionan mediante el modelo de datos, por defecto se utiliza el siguiente fichero alfresco/WEB-INF/classes/alfresco/model/contentModel.xml. Y las opciones para todos los contenidos, si no tenemos ningún tipo adicional es como sigue:

[xml]
<type name="cm:content">
<title>Content</title>
<parent>cm:cmobject</parent>
<properties>
<property name="cm:content">
<type>d:content</type>
<mandatory>false</mandatory>
<index enabled="true">
<atomic>false</atomic>
<stored>false</stored>
<tokenised>true</tokenised>
</index>
</property>
</properties>
</type>
[/xml]

A este respecto, cuando un documento se sube a Alfresco, los metadatos se extraen y se indexan en el acto, pero el contenido no tiene por que ser indexado en ese momento (depende). Veremos más abajo que significan estas opciones y qué nos aportan.
Como vemos en la parte <index enabled=”true”>, hay diferentes opciones en cuanto a los índices de las propiedades o de los contenidos:
  • Enabled=”false”: Si está a “false” no se indexará esa propiedad.
  • Atomic=”true”: Si está a “true”, esa propiedad (metadato) es indexada en el momento de la transacción, si está a “false”, se indexará en background. La indexación de contenidos que necesitan transformación antes de ser indexados (p. ej. PDF), solo serán “atomic=true” si la transformación tarda menos tiempo que el valor especificado en el atributo lucene.maxAtomicTransformationTime. Todos los transformadores por defecto están aquí alfresco/WEB-INF/classes/alfresco/services-context.xml.
  • Stored=”true”: Si está a “true”, el valor de la propiedad se almacenará en el índice y debe ser consultado mediante la API de bajo nivel de Lucene. Esto es útil para debugging si queremos saber qué es exactamente lo que se está indexando, pero no está recomendado en absoluto para producción ya que escribe mucha más información en disco. Recomendado “false”.
  • Tokenised=”true”: Si está “true”, el valor de la cadena de la propiedad se tokeniza antes de ser indexado. Si está a “false”, se indexará como una única cadena, si está a “both” se harán las dos opciones. Valor recomendado “true”.
Recuerda que por defecto todo el contenido, si se indexa, es “not stored”, indexed y tokenized.
  • Si quieres cambiar el comportamiento por defecto puedes hacerlo pero deberás reindexar todos los contenidos tras hacer el cambio. No te recomiendo tocar el modelo por defecto, es mejor hacer el tuyo propio y heredar valores o no, dependiendo de las necesidades que tengas. Recuerda que si haces un tipo que herede del tipo raíz “cm:content” no podrás desactivar el indexado del contenido.
  • Por defecto, las versiones de un documento (que se almacenan en el store workspace://version2Store) no se indexan. Ese comportamiento se podría modificar modificando el fichero core-services-context.xml como se puede ver aquí, referenciando la entrada version2Store al bean avmLuceneIndexerAndSearcherFactory igual que se pueden ver el workspace y el avm. Si lo haces recuerda que tendrás un consumo mucho más elevado de disco en los índices (dependerá del número de versiones que tengas por contenido, si no lo controlas bien no lo hagas, puede ser una bomba). Aunque actives la indexación del store de versiones, los formularios de búsqueda de Share o Explorer no buscarán en version2Store, pero se puede usar la API para realizar la búsqueda.
En cuanto a la recuperación de índices, es importante saber que existen cuatro modos FULL, AUTO, VALIDATE y NONE, que se usan en alfresco-global.properties mediante el atributo index.recovery.mode.
  • index.recovery.mode=FULL: Borra todos los índices actuales y genera un nuevo índice de todo el contenido (reindexa), durante este proceso el servidor no estará disponible.
  • index.recovery.mode=AUTO: Comprueba los primeros y últimos 1000 identificadores de transacción (txn) son válidos en cada store (información en la BBDD y en los índices coincide). Si no son válidos, se realizará una indexación FULL. En un cluster es importante tener sincronizados horariamente los servidores porque de lo contrario se lanzarán las reindexaciones al no coincidir la BBDD con los índices y la hora del servidor.
  • index.recovery.mode=VALIDATE: Comprueba los primeros y últimos 1000 identificadores de transacción (txn) son válidos en cada store (información en la BBDD y en los índices coincide). Si no son válidos, simplente devolverá una excepción.
  • index.recovery.mode=NONE: No se hace ningún tipo de validación en los índices.
Como vemos, los índices son muy importantes para Alfresco, tanto que si al arrancar encuentra algún problema grave en ellos, que no se solucione reindexando, el servidor se parará automáticamente. Este comportamiento se controla mediante el valor system.bootstrap.config_check.strict que por defecto está a “true”, podríamos ponerlo a “false” para poder analizar mejor algún problema concreto del que no tenemos mucha información en los logs (úsalo sólo para debug, afecta a otras opciones de configuración) y que evita que Alfresco arranque totalmente.
Al principio decía que los índices deben estar en discos locales (lo más rápidos disponibles y dedicados si es posible) para garantizar el máximo rendimiento de la aplicación. Para evitar problemas de lentitud es recomendable tener el doble del tamaño del índice total como espacio libre, para evitar problemas en caso de reindexación y sobre todo para el merge de los índices que se realiza a menudo. De hecho si compruebas que la subida de ficheros es muy lenta comprueba que tienes suficiente espacio libre en la partición o disco de los índices y que tienes correctamente configurados los file descriptors del sistema operativo (ver este artículo).
En caso de reindexación FULL podrás ver en los logs trazas como las siguientes:

[bash]
20:33:02,502 INFO [node.index.FullIndexRecoveryComponent] 100 % complete.
20:33:55,753 INFO [node.index.FullIndexRecoveryComponent] Index recovery completed.
[/bash]

Eso no significa que se hayan reindexado todos los contenidos, sólo nos indica que se han reindexado todas las propiedades (metadatos). A partir de ese momento Alfresco se pondrá a reindexar el contenido de los documentos. ¿Como podemos comprobar que está ocurriendo eso? Viendo la actividad en la CPU que puede provocar OpenOffice, ya que éste es utilizado para transformar ficheros MS Word a texto para poder ser indexados, por ejemplo.
Aunque ya lo comenté un poco en este artículo, quiero recordaros que existe el “Adminstrador de índices” o “Index Checker Console” disponible en la versión Enterprise desde la 3.1, puedes encontrarlo aquí: http://localhost:8080/alfresco/service/enterprise/admin/indexcheck. Esta consola te permite:
  • a) Comprobar los índices: por ejemplo, comprobar que cada transacción realizada por el repositorio está contemplada en los índices. Se puede comprobar por rangos de tiempo o rangos de transacciones.
  • b) Comprobar que un nodeRef específico o los nodos de una transacción específica están en el índice.
  • c) Reindexar desde un punto concreto hacia delante.
  • d) Comprobar el estado de sincronización de los índices entre transacciones y identificadores.
Bueno, esto ha sido todo, seguro que se quedan muchas cosas en el tintero pero espero que estos tips os resulten útiles e interesantes.

Cómo configurar Alfresco para usar Open Office remotamente, como servidor

Cuando vamos a tener un sistema con gran cantidad de usuarios (miles) y con necesidades importantes de transformación de formatos o incluso para lanzar una reindexación completa de ficheros, metadatos y contenido de los ficheros, puede ser útil escalar, ampliar nuestra infraestructura de Alfresco para usar recursos que tengamos disponibles en otras máquinas.

En este artículo voy a enseñar como configurar Alfresco Enterprise para usar un Open Office corriendo como servidor en un servidor remoto.

  • En el servidor dedicado donde ejecutaremos Open Office, que tiene la IP 192.168.0.30 ejecutamos el siguiente comando, poniendo la IP que será en la que “escuche” el proceso:

[bash]
/usr/bin/soffice -headless -nofirststartwizard -accept="socket,host=192.168.0.30,port=8100;urp;StarOffice.ServiceManager" &
[/bash]

  • En el servidor Alfresco, en el fichero alfresco-global.properties:

[bash]
### External executable locations ###
ooo.exe=/backup/alfresco/alfresco-enterprise-3.4.3/openoffice/program/soffice.bin
ooo.enabled=false
ooo.port=8100
ooo.server=192.168.0.30
img.root=/backup/alfresco/alfresco-enterprise-3.4.3/common
img.dyn=${img.root}/lib
img.exe=${img.root}/bin/convert
swf.exe=/backup/alfresco/alfresco-enterprise-3.4.3/common/bin/pdf2swf
jodconverter.enabled=true
jodconverter.officeHome=/backup/alfresco/alfresco-enterprise-3.4.3/openoffice
jodconverter.portNumbers=8100
[/bash]

Recuerda, en el archivo anterior, activar “jodconverter.enabled=true” y añadir el valor “ooo.server” con la IP donde estará el servidor dedicado con Open Office.

  • También creamos el siguiente fichero tomcat/shared/classes/alfresco/extension/remote-openoffice-context.xml con el contenido:

[xml]
<?xml version=’1.0′ encoding=’UTF-8′ ?>
<!DOCTYPE beans PUBLIC ‘-//SPRING//DTD BEAN//EN’ ‘http://www.springframework.org/dtd/spring-beans.dtd’>

<beans>

<bean id="openOfficeConnection" class="net.sf.jooreports.openoffice.connection.SocketOpenOfficeConnection">
<constructor-arg type="java.lang.String" value="${ooo.server}"/>
<constructor-arg type="int" value="${ooo.port}"/>
</bean>

<bean id="transformer.OpenOffice" class="org.alfresco.repo.content.transform.RemoteOpenOfficeContentTransformer" parent="baseContentTransformer" >
<property name="connection">
<ref bean="openOfficeConnection" />
</property>
<property name="documentFormatsConfiguration">
<value>classpath:alfresco/mimetype/openoffice-document-formats.xml</value>
</property>
</bean>

<bean id="openOfficeConnectionTester" class="org.alfresco.util.OpenOfficeConnectionTester">
<property name="connection">
<ref bean="openOfficeConnection"/>
</property>
<property name="strict">
<value>false</value>
</property>
</bean>

</beans>
[/xml]

Hechos esos cambios debemos reiniciar el servidor de aplicaciones y listo. Asegúrate que desde el servidor de Alfresco se llega al puerto de OpenOffice remoto por ejemplo haciendo “telnet 192.168.0.30 8100”, también puedes ver el tráfico que se genera entre los servidores lanzando el comando “tcpdump -nni eth0|grep 8100” en el servidor de OpenOffice.

Recuerda que esta es una funcionalidad de escalabilidad adicional que está disponible en Alfresco Enterprise. Yo la he probado con la versión 3.4.3.

Alfresco scheduled jobs, tareas automáticas de mantenimiento

Con el objetivo de ampliar el conocimiento en Alfresco y enseñar algunos aspectos que no se suelen tratar a menudo, en esta ocasión quiero explicar unos procesos que intervienen cada día en el mantenimiento de Alfresco y que generalmente desconocemos o no los tenemos en cuenta. Se trata de los “scheduled jobs”.
En Alfresco se ejecutan una serie de procesos automáticos de mantenimiento, algunos de ellos son nocturnos y otras se lanzan automáticamente cada cierto tiempo. Estas tareas son ajenas al usuario final pero no deberían serlo para los administradores de la plataforma. En docs.alfresco.com podréis encontrar información que os voy a resumir en este artículo.
Todos esas tareas están definidas en <configRoot>/scheduled-jobs-context.xml (cuando hablo de <configroot> me estoy refiriendo a la configuración dentro del fichero alfresco.war, ahí no debes tocarla, más abajo cuento como modificarlo, si fuese necesario). Algunas de las expresiones cron de estas tareas están definidas en <configRoot>/repository.properties. Recuerda que la sintaxis de este cron es diferente a la de UNIX, es Quartz y puedes ver ejemplos para entenderlo mejor aquí. si quieres cambiar algunas puedes hacerlo en alfresco-global.properties. Estas son las tareas de las que hablo:
  • contentStoreCleanerTrigger: Lanza el bean contentStoreCleaner, que identifica, borra o purga contenidos huérfanos del contentstore. Un contenido es huérfano cuando todas las referencias en la base de datos al binario se han eliminado. En un entorno en cluster este proceso se puede activar en un sólo nodo, con lo que se mejora el rendimiento durante el proceso. Por defecto se ejecuta a las 4:00 AM cada día (0 0 4 * * ?). El parámetro “ProtectDays” establece el número mínimo de días que el contenido debe ser huérfano antes de poder eliminarlo, el valor predeterminado es de 14 días.
  • nodeServiceCleanupTrigger: Realiza operaciones de limpieza en los nodos del DM, incluyendo transacciones antiguas y nodos antiguos eliminados. En un entorno en cluster este proceso se puede activar en un sólo nodo, con lo que se mejora el rendimiento durante el proceso. Se ejecuta a las 21:00h de cada día (0 0 21 * * ?).
  • openOfficeConnectionTesterTrigger: Monitoriza y mantiene la conexión con OpenOffice. Se ejecuta cada minuto (0 * * * * ?).
  • indexBackupTrigger: Hace un backup seguro de los directorios de Lucene. Crea el directorio “backup-lucene-indexes” y copia de forma segura la información de Lucene. Para conocer mejor como restaurarlo de forma incremental y evitar “FULL indexes” mira aquí. En un entorno en cluster este proceso se debe ejecutar en todos los nodos. Se ejecuta todos los días a las 3:00 AM (0 0 3 * * ?).
  • tempFileCleanerTrigger: Limpia todos los ficheros temporales de Alfresco cada cierto tiempo. También se vacían directorios temporales y sus subdirectorios. Existe un parámetro llamado “protectHours” que permite indicar el tiempo de conservación de un fichero temporal desde su última modificación. Por ejemplo, ficheros resultantes de transformaciones, extractores, temporales de OpenOffice, etc., generalmente almacenado en <tomcat>/temp/Alfresco. Se ejecuta cada hora en el minuto 30 (0 30 * * * ?).
  • avmOrphanReaperJob y avmExpiredContentTrigger: la primera tarea se ejecuta cada minuto para eliminar nodos huérfanos en el repositorio AVM y la segunda tarea sirve buscar contenido caducado en cada Web Project de WCM, se ejecuta cada día a las 3:30 AM. Si no has instalado AVM no te debes preocupar de esto, ya no se instala por defecto. Es el repositorio que usaba la implementación anterior de WCM.
  • ehCacheTracerJob: Recoge las estadísticas detalladas de uso de la caché y las salidas por consola, dependiendo de la configuración de logs del servidor. Por defecto, no está activado. Para activarlo hay que eliminar el comentario correspondiente en el xml de configuración. Si se activa, se ejecuta en intervalos de 60 minutos.
  • ftsIndexerTrigger: Esta tarea, aunque está en el fichero anterior, no es una tarea planificada en un momento concreto como tal, es para mantener los índices continuamente, se ejecuta cada minuto.
  • Cuando Alfresco está configurado en cluster hay un proceso llamado “index.tracking” que se lanza cada 5 segundos y se encarga de mantener los índices de todos los nodos del cluster sincronizados.
  • Sincronización de usuarios con LDAP: No es una tarea que que se gestione desde este fichero, pero es algo a tener en cuenta dentro de los trabajos planificados ya que dependiendo de la cantidad de usuarios que se sincronicen y la periodicidad de la sincronización, podría afectar al rendimiento de la plataforma. Una o dos veces al día, serían suficientes.
Recuerda que todos los detalles a bajo nivel de estas tareas específicas están descritas en el Java Doc de Alfresco en http://dev.alfresco.com/resource/docs/java/.
Estos trabajos planificados se pueden monitorizar mediante JXM en el bean Alfresco:Name=Schedule,Group=*,Type=*,Trigger=*
¿Cómo puedo cambiar el horario o configuración de estas tareas existentes? Hay dos formas de acceder a dicha información pero sólo una para modificarlos que es mediante archivos de configuración xml. Aunque si accedemos por JMX con la utilidad, por ejemplo, jconsole, podremos lanzar bajo demanda los procesos que necesitemos en cada momento o forzar la ejecución algún proceso concreto. Para cambiarlo modificando ficheros de configuración deberás copiar el fichero <configRoot>/alfresco/scheduled-jobs-context.xml a <extension>/custom-scheduled-jobs-context.xml y editarlo a tu gusto o necesidad.
Para ver los valores de las tareas y forzar su ejecución mediante JMX accede a tu servidor Alfresco con jconsole, aquí ves dos capturas, la primera es la vista general del bean:
y en la segunda vemos el ejemplo de la tarea que hace backup de los índices cada noche a las 3AM:
En la sección “Operations” de cada “Trigger” encontrarás un botón llamado “executeNow“, adivina para que sirve 😉 Cada tarea o trigger tiene una serie de propiedades que se explican por si solas, aunque me gustaría destacar la propiedad “Priority” que permite ejecutar una tarea sobre otra en caso de coincidir.
¿Cómo puedo hacer mi propia tarea planificada? Es algo que igual podría cubrir en un próximo artículo, de cualquier forma, puedes ver como hacerlo en esta página de la wiki. Y también puedes echar un vistazo al fichero <extension>/scheduled-action-services-context.xml.sample que es bastante ilustrativo.

Consejos sobre los logs en Alfresco

Como muchos ya sabréis, Alfresco utiliza Log4j para los logs. Log4j es una herramienta Open Source para gestionar logs y permite a programadores y administradores controlar lo que ocurre en la aplicación de forma granular y a diferentes niveles de detalle.

Controlar cómo funcionan los logs en Alfresco es la mejor forma de conocer como funciona el sistema tanto para administradores como programadores y poder detectar/solucionar problemas en una instalación.

Se configura mediante un fichero de texto llamado log4j.properties que se encuentra dentro de alfresco.war concretamente en el caso de Tomcat en ${TOMCAT_HOME}/webapps/alfresco/WEB-INF/classes. En este fichero se especifica qué queremos que registre el log y cómo queremos que lo muestre (mayor o menor detalle). También es donde se establece el nombre del fichero de log (alfresco.log) y los ficheros de log anteriores a los que le añade fecha (alfresco.log.YYYY-MM-DD). Estos ficheros de logs generados los encontraremos en la raíz del directorio donde hemos instalado Alfresco también conocido como ${ALFRESCO_HOME}, ojo, ni esta variable ni ${TOMCAT_HOME} existen salvo que se declaren, se usa para indicar el directorio raíz de instalación de Alfresco y de Tomcat respectivamente.

Vamos a ver como cambiar la ubicación del fichero de log de Alfresco. Copiamos el fichero log4j.properties al directorio extension con otro nombre, por ejemplo custom-log4j.properties:

[bash]
# cp ${TOMCAT_HOME}/webapps/alfresco/WEB-INF/classes/log4j.properties ${TOMCAT_HOME}/tomcat/shared/classes/alfresco/extension/custom-log4j.properties
[/bash]

Este cambio nos permitirá tener siempre la misma configuración de logs independientemente de que actualicemos Alfresco y despleguemos un nuevo alfresco.war donde se sobreescribiría la configuración personalizada si la hacemos dentro del war desplegado.

Editamos el fichero custom-log4j.properties y localizamos la línea:

[bash]
log4j.appender.File.File=alfresco.log
[/bash]

para especificar la siguiente:

[bash]
log4j.appender.File.File=/var/log/alfresco/alfresco.log
[/bash]

Como veis, este ejemplo está orientado a un sistema Linux o Unix, hay que tener en cuenta que si queréis poner los logs como he indicado hay que crear el directorio /var/log/alfresco y darle los permisos necesarios para que el usuario con el que se ejecuta Alfresco pueda escribir. También podríais poner los logs en alf_data/logs y así tener todo más centralizado. Para Windows habría que cambiar la ruta absoluta en el siguiente formato, por ejemplo “D:\logs\alfresco\alfresco.log”. Una recomendación de índole general para cualquier aplicativo y sus logs es disponer de una partición independiente encargado de almacenar estos ficheros (generalmente /var/log), de forma que si nos quedamos sin espacio en disco tanto en la aplicación como en los logs, no afecte al funcionamiento y podamos detectarlo de forma anticipada ya sea chequeando manualmente o con un sistema de monitorización, evidentemente también podemos poner una partición dedicada a los logs de Alfresco. Recuerda hacer backup de los logs regularmente.

Para entender mejor la sintaxis y opciones que encontramos en el fichero de configuración os recomiendo leer esta entrada en la Wikipedia. Destacaría el parámetro log4j.appender.File que especifica la rotación diaria del fichero de log y log4j.appender.File.File que permite indicar el nombre y path del fichero de log.

En cuanto a los niveles de detalle es importante conocer que existen los siguientes (de menos a mas detalle): OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE y ALL. Así que hay que tener cuidado con tener DEBUG, TRACE o ALL en un sistema en producción, salvo que sea necesario para solucionar un problema. Aquí puedes ver más información al respecto.

Si usáis un servidor de aplicaciones Tomcat, también es recomendable cambiar la ubicación del fichero de logs de Tomcat (o cualquier otro servidor de aplicaciones soportado), aquí vemos como cambiar el sitio donde se almacena el fichero catalina.out:

Editamos el fichero ${TOMCAT_HOME}/bin/catalina.sh, localizamos las líneas:

[bash]
if [ -z "$CATALINA_OUT" ] ; then
CATALINA_OUT="$CATALINA_BASE"/logs/catalina.out
fi
[/bash]

Y cambiamos la ruta de CATALINA_OUT por la ruta deseada:

[bash]
if [ -z "$CATALINA_OUT" ] ; then
CATALINA_OUT="/var/log/alfresco/catalina.out"
fi
[/bash]

Para que los cambios anteriores surtan efecto hay que reiniciar el servidor de aplicaciones. Una vez reiniciado ya veremos los ficheros creados en el directorio correspondiente.

Todo lo que hemos visto anteriormente se puede hacer de una forma más sencilla accediendo al servidor con jconsole mediante RMI y sin tener que reiniciar el servidor. En Alfresco Enterprise 3.4 ya está activado el acceso remoto. Aquí expliqué como acceder por jconsole a Alfresco.

Como vemos en la siguiente captura de pantalla, en la sección MBeans podemos encontrar un grupo llamado “log4j” y desplegado podemos ver todas sus opciones.

Concretamente en la captura anterior vemos los “Attributes” del bean “File“, y ahí podemos cambiar las opciones como por ejemplo “file”, el fichero y ruta de log. Una vez cambiado a nuestro gusto, para que tenga efecto vamos a “Operations“, hacemos clic en “activateOptions” y listo.

Por ejemplo, los logs de Webdav por defecto están configurados como detalle tipo “ERROR”, si queremos hacer un análisis más exhaustivo podríamos localizar el bean “org.alfresco.webdav.protocol” y desplegamos el menú “Attributes” y hacemos clic en “priority“, doble clic en “ERROR” para editarlo y lo cambiamos por “DEBUG” (sin comillas), a continuación guardamos simplemente pulsando la tecla “Enter” y ya tendríamos configurado el nivel de log del componente de turno. Fácil ¿no?

Para terminar quiero mencionar este pequeño desarrollo que ha realizado Tjarda Peelen – @tpeelen que permite ver los logs en la propia interfaz de la aplicación. Puede ser útil.

También se podría usar Log4mongo u otras aplicaciones para presentar logs vía web, pero eso ya es otra historia.

¿Algún consejo más? ¡Cualquier comentario es bienvenido!

Añade más utilidades de administración en Alfresco Share

Como muchos ya sabéis y también hablé aquí hace tiempo, Alfresco dispone de varios recursos internos que nos pueden ayudar en la administración y del servidor y también de cara a desarrollar. He preparado unos ficheros que nos permiten tener acceso a todos ellos de una forma sencilla y cómoda desde el menú de herramientas en Alfresco Share, como se puede ver aquí (pincha para ver la captura):

He creado un proyecto en Google Code para almacenar estos pequeños ficheros, lo he llamado alfresco-useful-admin-links. La instalación es muy sencilla, no hay que reiniciar el servidor:

  1. Descargar el conjunto de ficheros necesarios en el servidor desde aquí.
  2. Copia el contenido del fichero zip (sólo los ficheros contenido, no el directorio) en <tomcat home>/shared/classes/alfresco/web-extension/site-webscripts/org/alfresco/components/console. Si no existen esos directorios debes crearlos y si ya los tienes debes sobreescribir los ficheros existentes. Si no lo copias en esa dirección no te funcionará.
  3. Accede a la consola de Web Scripts de Alfresco Share http://localhost:8080/share/service/index.html
  4. Haz clic en “Refresh Web Scripts” y listo
  5. Accede a Alfresco Share, visita la sección “Herramientas” pinchando sobre el menú superior “Más…” -> “Repositorio

Lo he probado en Enterprise 3.4, si lo probáis en otras versiones y encontráis algún problema me indicáis para corregirlo.

Actualización: ¿Quieres instalarlo como AMP? Mira en el blog de Fernando Gonzalez, uno de los expertos españoles de Alfresco.

Video del webinar sobre “Clustering y escalabilidad en Alfresco”

Este es el video del webinar en el que hablamos sobre los componentes de la arquitectura que intervienen en Alfresco y que nos permiten escalar la plataforma ECM horizontal y verticalmente, así como conceptos y configuración de Alfresco en cluster para alta disponibilidad.

Recuerda que puedes encontrar más webinars en la sección ondemand de www.alfresco.com/es

Configuración de correo saliente desde Alfresco

Aunque ya hablé de esto hace tiempo, quiero hacer un update de esta información, a modo de nota mental.

Para notificaciones, invitaciones y demás avisos, Alfresco se puede configurar para que se conecte a un servidor de correo y envíe esos mensajes. Desde las versiones 3.3 y 3.4 esto es más fácil de configurar. Vamos a ver como se configura el correo saliente mediante SMTPS (seguro), si quieres hacer los envíos mediante los servidores de Gmail de forma autenticada y cifrada.

Simplemente añadiendo las siguientes  lineas en alfresco-global.properties:

[bash]
### Outbound mail SMTP ###
mail.host=smtp.gmail.com
mail.port=465
mail.protocol=smtps
mail.smtps.auth=true
[email protected]
mail.password=contraseña
mail.encoding=UTF-8
[email protected]
mail.smtp.starttls.enable=true
[/bash]

También se puede configurar un mensaje de test para que nos envíe un correo cada vez que arranca Alfresco y asegurarnos que el servicio funciona correctamente. Añadiríamos a alfresco-global.properties las siguientes líneas:

[bash]
### Test message when Alfresco starts ###
mail.testmessage.send=true
[email protected]
mail.testmessage.subject=Outbound mail from Alfresco, server started.
mail.testmessage.text=Outbound SMTP email subsystem is working. Installed on ${dir.root}
[/bash]

Aprovecho para poner este anuncio de la disponibilidad de Alfresco Community 3.4c y Enterprise RC1 en ESPAÑOL!!!

Alfresco EVT, herramienta para validación del entorno antes de instalar

Mi compañero en AlfrescoPeter Monks (Technical Director for Business Development), ha desarrollado un pequeño programa que permite validar el entorno donde se va a desplegar Alfresco tanto Enterprise como Community, aunque sin duda es más útil para Enterprise. Desde blyx.com quiero mostraros qué es y cómo funciona. Y dadas las fechas en las que estamos, a modo de regalo de Navidad.
Esta útil herramienta llamada Alfresco Environmente Validaton Tool (EVT) , comprueba varios puntos del sistema, base de datos y entorno específico, y nos muestra un informe donde podemos ver qué parámetros debemos cambiar para asegurarnos que Alfresco funcionará correctamente en nuestra red y enlaces donde encontrar esos recursos o recomendaciones. Básicamente analiza los puntos que desde Alfresco entendemos son más críticos o donde podemos encontrar problemas, de esta forma los evitamos.
Usarla es muy sencillo y funciona tanto en LINUX/UNIX como en windows ejecutando un script desde la línea de comandos. Claro, debe estar Java instalado en el sistema. Descomprimimos el zip que descargamos de la web del proyecto, ejecutamos  evt.sh o evt.cmd.

[bash]
# ./evt.sh -help

Usage: evt[.sh|.cmd] [-?|–help] [-v] [-V|-vv]
-t databaseType -h databaseHost [-r databasePort]
[-d databaseName] -l databaseLogin [-p databasePassword]

where: -?|–help – display this help
-v – produce verbose output
-V|-vv – produce super-verbose output (stack traces)
databaseType – the type of database. May be one of:
mysql, postgresql, oracle, mssqlserver, db2
databaseHost – the hostname of the database server
databasePort – the port the database is listening on (optional –
defaults to default for the database type)
databaseName – the name of the Alfresco database (optional –
defaults to ‘alfresco’)
databaseLogin – the login Alfresco will use to connect to the
database
databasePassword – the password for that user (optional)
[/bash]

Aquí vemos un ejemplo de la ejecución en un servidor Linux CentOS 5.5. No voy a usar la opción -vv porque no se ve bien en el blog, pero en tu caso ¡úsala! porque mostrará más información y recomendaciones para solucionar los problemas o alertas que detecte (INFO, WARN! y FAIL!!):
[bash]

# ./evt.sh -t mysql -h localhost -d alfresco -l alfresco -p alfresco

Alfresco Environment Validation Tool (for Alfresco Enterprise 3.3)
——————————————————————

Validating JVM
Vendor : Sun Microsystems Inc. …………………..PASS
Version : 1.6.0_21 ………………………………PASS
JVM Architecture : 32 bit ………………………………..INFO
Java Home : /usr/java/jre1.6.0_21 …………………..PASS

Validating Operating System
OS : Linux …………………………………PASS
Distribution : CentOS release 5.5 (Final) ………………WARN!
OS Architecture : 32 bit ………………………………..INFO
File Descriptors : 65535 …………………………………PASS

Validating Server Hardware
CPU Clock Speed : 2673Mhz ……………………………….PASS
CPU Count : 2 sockets, 2 cores ……………………..PASS
Installed RAM : 2032MB ………………………………..WARN!

Validating Network
Local Hostname : server ………………………………..PASS
IP Address : 10.10.100.100 ………………………….PASS
DNS Hostname : server.blyx.com ………………………..PASS
TCP 8005 (Tomcat) : available ……………………………..PASS
TCP 8080 (HTTP) : available ……………………………..PASS
TCP 50500 (RMI) : available ……………………………..PASS
TCP 21 (FTP) : available ……………………………..PASS
TCP 139 (NetBT) : available ……………………………..PASS
TCP 445 (SMB) : available ……………………………..PASS
TCP 7070 (Sharepoint) : available ……………………………..PASS
TCP 25 (SMTP) : available ……………………………..PASS
TCP 143 (IMAP) : available ……………………………..PASS
UDP 137 (NetBT) : available ……………………………..PASS
UDP 138 (NetBT) : available ……………………………..PASS
Database Hostname : resolved ………………………………PASS
Packet Loss : (please wait) 0% ……………………….PASS
Average Response Time : 0.186ms ……………………………….PASS
Response Time Std Dev : 0.042ms ……………………………….PASS

Validating 3rd Party Apps
Can fork OpenOffice : yes …………………………………..PASS
OpenOffice Version : unknown ……………………………….WARN!
Can fork ImageMagick : yes …………………………………..PASS
ImageMagick Version : 6.2 …………………………………..PASS
Can fork pdf2swf : yes …………………………………..PASS

Validating Database
Database Type : mysql …recognised …………………….PASS
JDBC Driver Loaded : yes …………………………………..PASS
Database Connectivity : connected ……………………………..PASS
Scrollable Result Sets: true ………………………………….PASS
JDBC Driver Version : 5.1 …………………………………..PASS
MySQL Version : 5.1.52 ………………………………..PASS
Default Storage Engine: InnoDB ………………………………..PASS
Case Sensitivity Level: 0 …………………………………….WARN!
Client Encoding : utf8 ………………………………….PASS
Connection Encoding : utf8 ………………………………….PASS
Database Encoding : latin1 ………………………………..FAIL!!
Filesystem Encoding : binary ………………………………..PASS
Results Encoding : utf8 ………………………………….PASS
Server Encoding : utf8 ………………………………….PASS
System Encoding : utf8 ………………………………….PASS

**** FINAL GRADE: FAIL!! ****

[/bash]

Como vemos en el report, se han analizado muchos puntos que pueden afectar al correcto funcionamiento de Alfresco:
  • Máquina virtual de Java.
  • Sistema Operativo (incluyendo file descriptors).
  • Hardware del servidor.
  • Información de la red, puertos disponibles y tiempos de respuesta con la base de datos.
  • Aplicaciones de terceros que necesita Alfresco para funcionar al 100%.
  • Configuración de la base de datos.
El ejemplo anterior tiene muchos errores para que veáis lo que puede detectar la herramienta. En ese sistema no sería recomendable instalar Alfresco.
Nota: recuerda ejecutar el comando antes de instalar Alfresco o con Alfresco parado, de lo contrario encontrarás muchos FAIL!! y WARN!

Espero que os sea útil.

A propósito, ¡Feliz Navidad a todos! ¡Y Feliz año 2011! Será el décimo aniversario de blyx.com (10 años desde que compré el dominio). Un año impar, seguro que es un buen año para todos.

¿Quieres prepararte? Aplicaciones empresariales Open Source

¿Estás estudiando? ¿No tienes trabajo y estás pensando en mejorar tu formación? ¿Quieres preparar tu perfil técnico pero no estás seguro por donde van las tendencias? Si eres o quieres ser técnico de sistemas, programador, administrador o arquitecto de sistemas o software y quieres trabajar con Software Libre, he preparado esta lista a modo de resumen y aprovechando que el curso acaba de empezar. Si no reunes las condiciones anteriores igual también te resulta interesante e incluso puedes ampliar la lista en los comentarios. (Parece que voy a vender cursos de CCC o algo así, pero nada más lejos de la realidad, es un simple listado :D).
La familia de aplicaciones “Enterprise Open Source” es bastante amplia y abarcan todos los campos que puede necesitar una organización. Si estas empezando en este mundo y eres capaz de dominar algunas de estas aplicaciones o conocerlas en profundidad, creo que tendrás más oportunidades en tu proyección profesional.
Antes de empezar, quiero dejar claro que este artículo no pretende ser un listado al estilo Infoworld, aunque dichas clasificaciones me parecen de un gran interés, en este caso sólo pretendo reflejar mis aplicaciones favoritas para cada caso y sobre todo, las que creo que están más extendidas.
Me gustaría recomendaros que echéis un vistazo a los “Amazon Elastic Compute Cloud” (Amazon EC2), es importante saber cómo funciona, cómo desplegar servidores, sistemas de almacenamiento que soporta, etc. En muchas empresas, se hacen uso de estos servicios, ya sea a través de Amazon u otros.
Bueno, aquí va la lista:
Muchas de estas aplicaciones las puedes instalar y probar de una forma muy sencilla y en Linux, Mac o Windows gracias a los stacks de Bitnami.
La mayoría de estas aplicaciones están hechas en PHP o en Java, eso te puede dar otra idea, si decides aprender a programar.
Hace un par de semanas, la empresa Stratebi publicó un listado que subraya algunas de las aplicaciones que aquí he indicado. Puedes ver la presentación aquí.
Tras hacer este listado he pensado que posiblemente no haya, o al menos yo no lo conozco, un centro de formación que capacite a técnicos y desarrolladores en todas estas tecnologías… sería algo interesante ¿no crees?

Monitoring Alfresco con Javamelody

Hace un tiempo leí este post sobre Monitorización de aplicaciones web con Javamelody escrito por Antonio Muñiz de Klicap y pensé que podría probarlo como no, con Alfresco. Así que me he puesto manos a la obra y aquí están los resultados.

En otros artículos (1, 2 y 3) he tratado de explicar las diferentes formas que existen para monitorizar Alfresco y tener una visión objetiva en cuanto al rendimiento de la aplicación, cuellos de botella, etc.

Hay métodos que son más intrusivos en cuanto a rendimiento que otros, por ejemplo, como indica Antonio en los comentarios de su artículo, el uso de VisualVM no sería viable para usos en producción ya que introduce retardos por cada línea de código ejecutada, JConsole (que viene con la JDK) no es tan intrusiva ya que sólo hace lecturas vía JMX de la información que ofrece la JVM (así es como funciona el plugin de Nagios para Alfresco). En el caso que nos ocupa, Javamelody, el impacto en la aplicación monitorizada es mucho menor que las anteriores ya que no se ataca directamente a la aplicación a monitorizar sino que se usan unos jars dedicados a la tarea de extraer la información.

La instalación de Javamelody es sencilla y aunque puedes ver más opciones aquí, estos son los pasos básicos para instalar la aplicación:

  • Paramos Alfresco (en mi caso la versión 3.3), no es obligatorio.
  • Descomprimimos el archivo zip.
  • Copiamos los ficheros javamelody-1.19.0.jar y jrobin-1.5.9.1.jar al directorio WEB-INF/lib que está dentro del directorio webapps/alfresco (puede variar dependiendo del servidor de aplicaciones), es el directorio que se crea automáticamente cuando desplegamos alfresco.war.
  • Por último añadimos las siguientes líneas en el fichero WEB-INF/web.xml de la aplicación, dentro de las etiquetas web-app:

[xml]
<filter>
<filter-name>monitoring</filter-name>
<filter-class>net.bull.javamelody.MonitoringFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>monitoring</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>net.bull.javamelody.SessionListener</listener-class>
</listener>
[/xml]

  • Opcionalmente, para poder generar informes en PDF debemos copiar a WEB-INF/lib el fichero itext-2.1.7.jar que podemos encontrar dentro del zip descargado en src/test/test-webapp/WEB-INF/lib/
  • Accedemos via web http://localhost:8080/alfresco/monitoring

Añadir a todo lo anterior unas notas:

  • Todos los ficheros generados por RRD se encuentran en tomcat/temp/javamelody.
  • Recuerda que al estar los ficheros de Javamelody dentro del directorio alfresco (alfresco.war desplegado), cuando actualices Alfresco deberás volver a hacer el procedimiento de instalación de Javamelody.
  • La web que nos muestra las estadísticas no tiene ningún tipo de protección por usuario y contraseña ya que es una web de consulta, no obstante, se podría establecer, mira aquí.

Dicho todo lo anterior ¿qué obtenemos? Aquí podemos ver algunas capturas de pantalla y otras muchas en este enlace:

Como comentaba anteriormente, lo he probado en Alfresco 3.3 Enterprise pero dadas las características de Javamelody debe funcionar en la versión Community. Espero vuestro feedback.

ACTUALIZACIÓN 16/Sept/2010:

Cuando arrancamos Alfresco tras haber copiado los ficheros jar, posiblemente veamos en el log de Tomcat, unas trazas como las siguientes (este error no afecta al rendimiento de la aplicación):

ERROR [log4j.jmx.LoggerDynamicMBean] Could not add appenderMBean for [null]. java.lang.NullPointerException: Invalid value (null)
at net.bull.javamelody.Log4JAppender.register(Log4JAppender.java:50)
 at net.bull.javamelody.MonitoringFilter.initLogs(MonitoringFilter.java:272)
 at net.bull.javamelody.MonitoringFilter.init(MonitoringFilter.java:98)

Contacté con el desarrollador de Javamelody, Emeric Vernat y muy amablemente me envió una nueva versión de uno de los jars que soluciona ese problema, se trata de este: http://javamelody.googlecode.com/files/javamelody-20100915.jar. Para actualizar el jar debemos parar Alfresco, borrar el fichero <tomcat>/webapps/alfresco/WEB-INF/lib/javamelody-1.19.0.jar y copiar javamelody-20100915.jar en el directorio donde se encontraba el anterior. Arrancamos Alfresco y listo. Muchas gracias por el feedback Emeric!!

MAS INFO ACTUALIZADA A 12/12/12 AQUI: https://tpeelen.wordpress.com/2012/12/12/alfresco-monitoring-with-javamelody/