
Somos el departamento de desarrollo de tecnologías para la red minorista. En una ocasión, la dirección planteó la tarea de acelerar los cálculos volumétricos utilizando Apache Ignite junto con MSSQL, mostrando un sitio web con magníficas ilustraciones y ejemplos de código Java. Desde el primer momento, me gustó el sitio. , cuya descripción promete maravillas: no tienes que implementar manualmente tu código Java o Scala en cada nodo de la cuadrícula y volver a implementarlo cada vez que cambia. Durante el proceso, resultó que Zero Deployment tiene características particulares de uso, de las cuales quiero compartir. A continuación, reflexiones y detalles sobre la implementación.
1. Planteamiento del problema
La esencia del problema es la siguiente. Hay un directorio de puntos de venta SalesPoint y un directorio de productos Sku (Stock Keeping Unit). Cada punto de venta tiene un atributo ‘tipoTienda’ con los valores ‘pequeño’ y ‘grande’. A cada punto de venta se le conecta (cargado desde la base de datos) un surtido (lista de productos del punto de venta) y se presenta información sobre que, a partir de una fecha indicada, el producto especificado
se excluye del surtido o se añade al surtido.
Se requiere organizar una caché particionada de puntos de venta y almacenar en ella información sobre los productos conectados para un mes adelante. La compatibilidad con el sistema en producción exige que el nodo cliente de Ignite cargue datos, calcule un agregado del tipo (tipoTienda, códigoProducto, día, número_puntos_venta) y lo descargue de nuevo en la base de datos.
2. Estudio de la literatura
Como aún no tengo experiencia, empiezo desde cero. Es decir, con una revisión de publicaciones.
Un artículo de 2016 contiene un enlace a la documentación del proyecto Apache Ignite y, de paso, una crítica a la falta de claridad de esta documentación. Lo he leído un par de veces, pero la claridad no llega. Me dirijo al tutorial oficial , quien
que optimistamente promete ‘¡Estarás funcionando en un instante!’. Estoy revisando la configuración de las variables de entorno, veo dos videos sobre Apache Ignite Essentials, que para mi tarea específica resultaron no ser muy útiles. Puedo iniciar Ignite desde la línea de comandos con el archivo estándar ‘example-ignite.xml’, y construyo mi primera aplicación utilizando Maven. ¡La aplicación funciona y utiliza Zero Deployment, qué belleza!
Sigo leyendo, y ahí hay un ejemplo que utiliza affinityKey (creado anteriormente mediante una consulta SQL), además se aplica un misterioso BinaryObject:
IgniteCache<BinaryObject, BinaryObject> people
= ignite.cache("Person").withKeepBinary(); He leído : formato binario: algo así como reflexión, acceso a los campos del objeto por nombre. Puede leer el valor del campo sin deserializar completamente el objeto (ahorro de memoria). Pero, ¿por qué se utiliza BinaryObject en lugar de Person, si ya existe Zero Deployment? ¿Por qué IgniteCache se traduce a IgniteCache? Aún no está claro.
Estoy adaptando la aplicación de cálculo para mi caso. La clave primaria del directorio de puntos de venta en MSSQL se define como [id] [int] NOT NULL, creo la caché por analogía.
IgniteCache salesPointCache=ignite.cache("spCache")En la configuración xml indico que la caché es particionada.
La partición por puntos de venta supone que el agregado requerido se construirá en cada nodo del clúster para los registros existentes en salesPointCache, tras lo cual el nodo cliente realizará la suma final.
Leo un tutorial , lo hago por analogía. En cada nodo del clúster, ejecuto IgniteRunnable(), más o menos así:
@Override
public void run() {
SalesPoint sp=salesPointCache.get(spId);
sp.calculateSalesPointCount();
..
}Agrego la lógica de agregación y descarga, ejecuto en un conjunto de datos de prueba. Localmente en el servidor de desarrollo todo funciona.
Inicio dos servidores de prueba CentOs, indico las direcciones IP en default-config.xml, ejecuto en cada uno
. /bin/ignite.sh config/default-config.xmlAmbos nodos de Ignite se inician y se ven entre sí. Indico las direcciones necesarias en el xml de configuración de la aplicación cliente, se inicia, agrega un tercer nodo a la topología y de inmediato el número de nodos vuelve a ser dos. En el registro aparece «ClassNotFoundException: model.SalesPoint» en la línea
SalesPoint sp=salesPointCache.get(spId);StackOverflow dice que la causa del error es que en los servidores CentOs no está la clase de usuario SalesPoint. Hemos llegado. ¿Qué pasó con «you don’t have to manually deploy your Java code on each node» y así sucesivamente? O «your Java code» — ¿no se refiere a SalesPoint?
Probablemente he pasado algo por alto: empiezo a buscar, leer y buscar nuevamente. Después de un tiempo da la sensación de que he leído todo sobre el tema, no hay nada nuevo. Mientras buscaba, encontré algunas observaciones interesantes.
, Arquitecto Principal en GridGain Systems, en StackOverflow, abril de 2016:
Las clases del modelo no se implementan entre pares, pero puedes usar la bandera withKeepBinary() en la caché y consultar BinaryObjects. De esta manera evitarás la deserialización del lado del servidor y no obtendrás ClassNotFoundException.Otra opinión autorizada: , Director de gestión de productos, GridGain Systems.
Artículo en Habré hace referencia a tres artículos de Denis Magda: , , de 2016 a 2017. En el segundo artículo Denis sugiere iniciar un nodo de clúster a través de MaintenanceServiceNodeStartup.jar. También se puede utilizar el lanzamiento con configuración xml y línea de comandos, pero en ese caso hay que colocar manualmente las clases de usuario en cada nodo del clúster que se despliega:
Eso es todo. Inicia (..) el nodo usando el archivo MaintenanceServiceNodeStartup o pasa
maintenance-service-node-config.xml a los scripts ignite.sh/bat de Apache Ignite.
Si prefieres lo último, asegúrate de construir un archivo jar que contenga
todas las clases de los directorios java/app/common y java/services/maintenance.
El jar debe añadirse al classpath de cada nodo donde el servicio
podría ser desplegado.De hecho, eso es todo. ¡Aquí está, por lo visto, la razón de este misterioso formato binario!
3. SingleJar
Denis ocupó el primer lugar en mi ranking personal, en mi opinión, el tutorial más útil de todos los disponibles. En su en GitHub se encuentra un ejemplo completamente listo de configuración de nodos de clúster, que se compila sin ningún esfuerzo adicional.
Hago por analogía y obtengo un único archivo jar, que inicia el «data node» o el «client node» dependiendo del argumento de la línea de comandos. La construcción se inicia y funciona. Zero Deployment ha sido derrotado.
La transición de megabytes de datos de prueba a decenas de gigabytes de datos en producción mostró que el formato binario no existe en vano. Fue necesario optimizar el consumo de memoria en los nodos, y aquí BinaryObject resultó ser muy útil.
4. Conclusiones
La primera crítica que encontré sobre la falta de claridad en la documentación del proyecto Apache Ignite resultó ser justa, desde 2016 ha cambiado poco. A un novato no le resulta fácil crear un prototipo funcional a partir del sitio y/o el repositorio.
Como resultado del trabajo realizado, tengo la impresión de que Zero Deployment funciona, pero solo a nivel del sistema. Más o menos así: BinaryObject se aplica para enseñar a los nodos remotos del clúster a trabajar con las clases de usuario; Zero Deployment es un mecanismo interno
del propio Apache Ignite y distribuye objetos del sistema por el clúster.
Espero que mi experiencia sea útil para los nuevos usuarios de Apache Ignite.
Fuente: habr.com
