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.
- 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.